数三角题解【noip难题】

该博客介绍了如何解决一个数三角形的游戏问题,其中木棍可以水平、垂直或对角线放置。博主通过整理数据,使用曼哈顿距离判断木棍是否连接,并通过“弗洛伊德”算法进行联通判断。文章提供了详细的思路和代码实现,包括如何判断两点共线和处理特殊情况。
摘要由CSDN通过智能技术生成

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 + 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值