数三角
【问题描述】
这是一个数三角的游戏。长度为 1 或 SQRT(2)的小木棍放在一个网格上。如图所示,有
水平的,垂直的或对角的。对角放置的木棍可以交叉。
将木棍随意地放在网格上得到的图案可能不含三角形,
也可能含一个或多个三角形。
如
下图所示,
(a),(b),(c),(d)和(e)分别含有 2,5,12,0,0 个三角形。
你的任务是写一个程序数出一个图案中的三
角形个数。
【输入】
输入文件 count.in 包括 N+1 行:
先输入图案中木棍的个数 N。下面输入这 N 根木棍的位置,用两个网格坐标表示,这
两个坐标分别为木棍两端的位置。网格大小不超过 1010,因此网格左下和右上的坐标分别
为(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.