1.题目:
这是一个数三角的游戏。长度为1或SQRT(2)的小木棍放在一个网格上。如图所示,有水平的,垂直的或对角的。对角放置的木棍可以交叉。
将木棍随意地放在网格上得到的图案可能不含三角形,也可能含一个或多个三角形。如下图所示,
(a),(b),©,(d)和(e)分别含有2,5,12,0,0个三角形。你的任务是写一个程序数出一个图案中的三角形个数。。cpp
输入文件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
题解:
一 :整理数据:
设a[i][j][k][l]表示(i, j)与(k, l)有联通;
首先输入x1, _y, x2, y2分别表示两点坐标,之后再将每个点×2,使得之后判断对角线情况更加容易(要不然会出现下标为小数情况)。
1.在同一直线,即是曼哈顿距离为2:
1):此时若两点为水平的(x1 == x2),那么A,C联通, C,B联通,同时将A,B连通(因为可能B在A前面所以要判断一下,但方法和此时相同),注意为了防止之后的联通路有问题,所以还要将点反过来在标记一遍如b[A][B]=b[B][A] = 1
if(x1 + _y - x2 - y2 == 2) {
if(x1 == x2) {
//如果两点在同一水平线上
a[x1][_y + 1][x1][y2] = 1;//B,C
a[x1][y2][x1][_y + 1] = 1;//反过来
a[x1][_y + 1][x1][_y] = 1;//A,C;
a[x1][_y][x1][_y + 1] = 1;//反过来
}
}//这里只写了B在A前的情况,另一种读者自行思考
2):若两点为竖直状态(y1 == y2)同样A,C联通, C,B联通,同时将A,B连通,还有也要判断B在A上面的情况,以及反复标记。
if(x1 + _y - x2 - y2 == 2) {
//如果两点在同一水平线上
if(_y == y2) {
//若竖着的一条线
a[x1 + 1][_y][x2][_y] = 1;
a[x2][_y][x1 + 1][_y] = 1;//两点分别连一次
a[x1 + 1][_y][x1][_y] = 1;
a[x1][_y][x1 + 1][_y] = 1;
}//这里只写了B在A上的情况,另一种读者自行思考
}
2.在两对角线上,即是曼哈顿距离为4:
1):如图如果是这种状态,那么同理连接A,C与B,C和A, B,注意C可表示为(bx + 1, by + 1),同样的这里也有A在前或B在前的情况。
if(x1 + _y - x2 - y2 == 4) {
//B在前
a[x1][_y][x2 + 1][y2 + 1] = 1;//连接A,C
a[x2 + 1][y2 + 1][x1][_y] = 1;//反向连接
a[x2][y2][x2 + 1][y2 + 1] = 1;//连接B,C
a[x2 + 1][y2 + 1][x2][y2] = 1;
}
if(x2 + y2 - x1 - _y == 4) {
//A在前
a[x1 + 1][_y + 1][x2][y2] = 1;//B,C
a[x2][y2][x1 + 1][_y + 1] = 1;
a[x1][_y][x1 + 1][_y +