题目描述
这是一个数三角的游戏。长度为1或SQRT(2)的小木棍放在一个网格上。如图所示,有水平的,垂直的或对角的。对角放置的木棍可以交叉。
将木棍随意地放在网格上得到的图案可能不含三角形,也可能含一个或多个三角形。如下图所示,
( a ) , ( b ) , ( c ) , ( d ) (a),(b),(c),(d) (a),(b),(c),(d) 和 ( e ) (e) (e) 分别含有 2 , 5 , 12 , 0 , 0 2,5,12,0,0 2,5,12,0,0 个三角形。你的任务是写一个程序数出一个图案中的三角形个数。。
输入格式
输入文件count.in包括N+1行:
先输入图案中木棍的个数N。下面输入这N根木棍的位置,用两个网格坐标表示,这两个坐标分别为木棍两端的位置。网格大小不超过10´10,因此网格左下和右上的坐标分别为(0,0)和(9,9)。
输出格式
输入文件count.out包括1行:
三角形的个数。
样例
样例输入
3
0 0 0 1
0 0 1 0
0 1 1 0
样例输出
1
思路
由 C2021ljs 提供。
首先在输入进来时,我们将所有的坐标过大两倍,也就是将每个网格又分成四个小格。这样的好处是什么呢?这样的话,在整个过程中就不会忽略如图 ( c ) (c) (c) 中被划分出的小三角形。
然后对于输入进来的木棍,我们需要标记它们连通(即之间有木棍),并且它们与木棍的中点也是连通的(网格过大后产生的),所以在输入时,我们可以将这些一起处理了。
int lx[25][25][25][25]; //lx[i][j][x][y]表示(i,j)(x,y)之间有连线,连通
for (int i = 1; i <= n; i++) {
int a, b, x, y;
scanf("%d %d %d %d", &a, &b, &x, &y);
a <<= 1; b <<= 1; x <<= 1; y <<= 1;
lx[a][b][(a + x) >> 1][(b + y) >> 1] = 1;
lx[(a + x) >> 1][(b + y) >> 1][a][b] = 1;
lx[x][y][(a + x) >> 1][(b + y) >> 1] = 1;
lx[(a + x) >> 1][(b + y) >> 1][x][y] = 1;
//(a,b),(x,y)连线的中点坐标为((a+x)/2,(b+y)/2)
lx[a][b][x][y] = 1;
lx[x][y][a][b] = 1;
}
接下来我们可以想, a a a 点与 b b b 点连通, a a a 点又与 c c c 点连通,那么只要 a , b , c