【细心题】数三角

数三角
【问题描述】
这是一个数三角的游戏。长度为 1 或 SQRT(2)的小木棍放在一个网格上。如图所示,有
水平的,垂直的或对角的。对角放置的木棍可以交叉。
将木棍随意地放在网格上得到的图案可能不含三角形,
也可能含一个或多个三角形。

下图所示,
(a),(b),(c),(d)和(e)分别含有 2,5,12,0,0 个三角形。
你的任务是写一个程序数出一个图案中的三
角形个数。
【输入】
输入文件 count.in 包括 N+1 行:
先输入图案中木棍的个数 N。下面输入这 N 根木棍的位置,用两个网格坐标表示,这
两个坐标分别为木棍两端的位置。网格大小不超过 1010,因此网格左下和右上的坐标分别
为(0,0)和(9,9)。
【输出】
输入文件 count.out 包括 1 行:
三角形的个数。
【输入输出样例】
count.in
3 1
0001
0010
0110

count.out

1

program count;

{
Col:合肥一中冲刺 NOIP2012 训练(二)
Prob:count
Date:2012/10/09
BY:HT
}

{4    3    2
  \   |   /
    \ | /
 5----*----  1
    / | \
  /   |   \
 6    7    8
}

uses math;

Const
 dx:array[1..8] of longint=(1,1,0,-1,-1,-1,0,1);
 dy:array[1..8] of longint=(0,1,1,1,0,-1,-1,-1);
 op:array[1..8] of longint=(5,6,7,8,1,2,3,4);

Var
 a:array[-2..20,-2..20,0..8] of boolean;
 f:array[-2..20,-2..20,0..8] of longint;
 n,i,j,k,x1,y1,x2,y2,ans:longint;


Procedure fopen;
  begin
  assign(input,'count.in');
  assign(output,'count.out');
  reset(input);
  rewrite(output);
end;

Procedure fclose;
  begin
  close(input);
  close(output);
end;

  begin
  fopen;
  fillchar(a,sizeof(a),false);
  readln(n);
  for i:=1 to n do
    begin
    readln(x1,y1,x2,y2);
    for j:=1 to 8 do
      if (x2=x1+dx[j]) and (y2=y1+dy[j]) then
        begin
        a[x1,y1,j]:=true;
        a[x2,y2,op[j]]:=true;
      end;
  end;

  for i:=0 to 9 do
    for j:=0 to 9 do
      for k:=5 to 8 do
        if a[i,j,k] then f[i,j,k]:=f[i+dx[k],j+dy[k],k]+1;

  for i:=0 to 9 do
    for j:=0 to 9 do
      for k:=1 to 4 do
        if a[i,j,k] then f[i,j,k]:=f[i+dx[k],j+dy[k],k]+1;
  ans:=0;
 { for i:=0 to 9 do
    for j:=0 to 9 do
      begin
      writeln('(',i,',',j,') :');
      for k:=1 to 8 do
        writeln(f[i,j,k]);
    end;   }
  //point(x,y)
  for i:=0 to 9 do
    for j:=0 to 9 do
      begin
      //case 1     |_
      for k:=1 to min(f[i,j,1],f[i,j,3]) do
        if f[i+dx[1]*k,j+dy[1]*k,4]>=k then inc(ans);
      //case 2    \/
      for k:=1 to min(f[i,j,2],f[i,j,4]) do
        if f[i+dx[2]*k,j+dy[2]*k,5]>=k then inc(ans);
      //case 3   _|
      for k:=1 to min(f[i,j,3],f[i,j,5]) do
        if f[i+dx[3]*k,j+dy[3]*k,6]>=k then inc(ans);
      //case 4   \
      //         /
      for k:=1 to min(f[i,j,4],f[i,j,6]) do
        if f[i+dx[4]*k,j+dy[4]*k,7]>=k then inc(ans);
      //case 5  --
      //         |
      for k:=1 to min(f[i,j,5],f[i,j,7]) do
        if f[i+dx[5]*k,j+dy[5]*k,8]>=k then inc(ans);
      //case 6  /\
      for k:=1 to min(f[i,j,6],f[i,j,8]) do
        if f[i+dx[6]*k,j+dy[6]*k,1]>=k then inc(ans);
      //case 7    |-
      for k:=1 to min(f[i,j,7],f[i,j,1]) do
        if f[i+dx[7]*k,j+dy[7]*k,2]>=k then inc(ans);
      //case 8   /
      //         \
      for k:=1 to min(f[i,j,8],f[i,j,2]) do
        if f[i+dx[8]*k,j+dy[8]*k,3]>=k then inc(ans);
    end;

  //points in squere
  for i:=0 to 8 do
    for j:=0 to 8 do
      begin
      for k:=1 to min(f[i,j,2],f[i,j+1,8]) do
        if f[i+dx[2]*k,j+dy[2]*k,7]>=k then inc(ans);
      for k:=1 to min(f[i,j,2],f[i+1,j,4]) do
        if f[i+dx[2]*k,j+dy[2]*k,5]>=k then inc(ans);
      for k:=1 to min(f[i+1,j+1,6],f[i+1,j,4]) do
        if f[i+1+dx[4]*k,j+dy[4]*k,7]>=k then inc(ans);
      for k:=1 to min(f[i+1,j+1,6],f[i,j+1,8]) do
        if f[i+1+dx[6]*k,j+1+dy[6]*k,1]>=k then inc(ans);
    end;

  writeln(ans);
  fclose;
end.
原文地址:https://www.cnblogs.com/htfy/p/2717371.html