poj1127

Jack Straws

Time Limit: 1000MS Memory Limit: 10000K

Description

In the game of Jack Straws, a number of plastic or wooden “straws” are dumped on the table and players try to remove them one-by-one without disturbing the other straws. Here, we are only concerned with if various pairs of straws are connected by a path of touching straws. You will be given a list of the endpoints for some straws (as if they were dumped on a large piece of graph paper) and then will be asked if various pairs of straws are connected. Note that touching is connecting, but also two straws can be connected indirectly via other connected straws.

Input

Input consist multiple case,each case consists of multiple lines. The first line will be an integer n (1 < n < 13) giving the number of straws on the table. Each of the next n lines contain 4 positive integers,x1,y1,x2 and y2, giving the coordinates, (x1,y1),(x2,y2) of the endpoints of a single straw. All coordinates will be less than 100. (Note that the straws will be of varying lengths.) The first straw entered will be known as straw #1, the second as straw #2, and so on. The remaining lines of the current case(except for the final line) will each contain two positive integers, a and b, both between 1 and n, inclusive. You are to determine if straw a can be connected to straw b. When a = 0 = b, the current case is terminated.

When n=0,the input is terminated.

There will be no illegal input and there are no zero-length straws.

Output

You should generate a line of output for each line containing a pair a and b, except the final line where a = 0 = b. The line should say simply “CONNECTED”, if straw a is connected to straw b, or “NOT CONNECTED”, if straw a is not connected to straw b. For our purposes, a straw is considered connected to itself.

Sample Input

7
1 6 3 3
4 6 4 9
4 5 6 7
1 4 3 5
3 5 5 5
5 2 6 3
5 4 7 2
1 4
1 6
3 3
6 7
2 3
1 3
0 0

2
0 2 0 0
0 0 0 1
1 1
2 2
1 2
0 0

0

Sample Output

CONNECTED
NOT CONNECTED
CONNECTED
CONNECTED
NOT CONNECTED
CONNECTED
CONNECTED
CONNECTED
CONNECTED

Source

East Central North America 1994

Solution

题意:判断两条线段是否相交,对于N条线段,间接相交也算相交。对于每次询问,判
断给定的两条线段是否相交。

扫描二维码关注公众号,回复: 9445381 查看本文章

这个题目分成两部分,一部分是基础的判断两条线段是否相交,用一个bool数组来存储信息。另一部分是判断间接相交,可以用floyd-warshall(比较巧妙)或者并查集.第一部分就是套模板。

点可以用结构体存储(推荐),线段也可以用结构体存储或pair

判断两条线段相交有多重模板,比如判是否平行、重合、求两条直线交点,判断交点是否在线段上,还有ccw(counter clock wise)函数,可参考discuss

比较常见的是快速排斥跨立检验

以线段为对角线,作平行于x轴、y轴的射线,使之形成矩形,若两个矩形没有相交,则线段不相交(可以排除大部分)

不满足快速排斥进入跨立检验,判断两个点是否在线段的两侧(即跨立),判断方法是外积的符号是否相反,等于0说明在线上

如果两两互相跨立,则线段相交

#include<iostream>
#include<algorithm>
using namespace std;
int n;
bool con[15][15];
int p,q;
struct point
{
	double x,y;
	//point(double a,double b) : x(a),y(b) {}            //!!!!!会发生编译错误 
};
pair<point,point> seg[15];
double dir(point a,point b,point c) //用外积 
{
	return (c.x-a.x)*(c.y-b.y) - (c.y-a.y)*(c.x-b.x); 
}
bool judge(pair<point,point> p1,pair<point,point> p2)
{
	point a,b,c,d;
	a=p1.first; 
	b=p1.second;
	c=p2.first;
	d=p2.second;
	//快速排斥
	if(min(a.x,b.x)>max(c.x,d.x) or min(c.x,d.x)>max(a.x,b.x) or
	   min(a.y,b.y)>max(c.y,d.y) or min(c.y,d.y)>max(a.y,b.y))
	   return false;
	//跨立检验 (int 可改成double)
	else
	{
		int d1,d2,d3,d4;
		d1=dir(a,b,c);
		d2=dir(a,b,d);
		d3=dir(c,d,a);
		d4=dir(c,d,b);
		return d1*d2<=0 and d3*d4<=0;    //!!!
	}
}
int main()
{
	//freopen("input.txt","r",stdin);
	while(scanf("%d",&n)==1 and n!=0)
	{
		for(int i=1;i<=n;i++) con[i][i]=true;
		for(int i=1;i<=n;i++)
			scanf("%lf%lf%lf%lf",&seg[i].first.x,&seg[i].first.y,&seg[i].second.x,&seg[i].second.y);
		for(int i=1;i<=n;i++)
			for(int j=1;j<i;j++)
			{
				if(judge(seg[i],seg[j])) con[i][j]=con[j][i]=true;
				else con[i][j]=con[j][i]=false;
			}
		for(int k=1;k<=n;k++)                                               //Floyd-Warshall算法或并查集都可以 
			for(int i=1;i<=n;i++)
				for(int j=1;j<=n;j++)
					con[i][j] |= con[i][k] and con[k][j];
		while(scanf("%d%d",&p,&q)==2 and p!=0)
			puts(con[p][q] ? "CONNECTED" : "NOT CONNECTED");
	}
	return 0;
}
艰难的debug

计算几何有些很麻烦,代码太相似,debug比较难,有时还要考虑精度问题(即误差eps)

debug一个上午

写完代码CE,seg[i].first.x错误,把stl_pair.h中的代码小改一下可以通过,但放到oj上肯定不行,怕污染代码还是不这样做。最后发现把构造函数去掉可以通过

自测,最后一个样例没过,发现是边界情况,把跨立检验最后一步的等号加上

自测,中间有一个样例没过,作图,把样例分离出来,过了。说明可能不是judge函数的问题。

单测样例,没过,说明错误不是受别组影响

编译器debug,把函数内的局部变量,变成全局变量,add watch

发现d1 d2 d3 d4都等于0,a.x a.y b.x b.y …有问题

继续add watch

发现seg[1].first的内容就有问题,是double边界数,然后发现最终问题 %d 赋值给了double型变量

总结

提高debug能力,少犯白痴错误。

写代码要有清晰性和完整性,这样鲁棒性更强。

发布了25 篇原创文章 · 获赞 0 · 访问量 545

猜你喜欢

转载自blog.csdn.net/qq_43737697/article/details/104092861