POJ 3304 && Segments (計算幾何)(枚舉+叉乘判斷是否規範相交)

Language:
Segments
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 19092 Accepted: 6026
Description

Given n segments in the two dimensional space, write a program, which determines if there exists a line such that after projecting these segments on it, all projected segments have at least one point in common.

Input

Input begins with a number T showing the number of test cases and then, T test cases follow. Each test case begins with a line containing a positive integer n ≤ 100 showing the number of segments. After that, n lines containing four real numbers x1 y1 x2 y2 follow, in which (x1, y1) and (x2, y2) are the coordinates of the two endpoints for one of the segments.

Output

For each test case, your program must output “Yes!”, if a line with desired property exists and must output “No!” otherwise. You must assume that two floating point numbers a and b are equal if |a - b| < 10-8.

Sample Input

3
2
1.0 2.0 3.0 4.0
4.0 5.0 6.0 7.0
3
0.0 0.0 0.0 1.0
0.0 1.0 0.0 2.0
1.0 1.0 2.0 1.0
3
0.0 0.0 0.0 1.0
0.0 2.0 0.0 3.0
1.0 1.0 2.0 1.0
Sample Output

Yes!
Yes!
No!
Source

Amirkabir University of Technology Local Contest 2006

題目大意:
給定一些線段,問是否有直線L存在,使得 所有線段到L的投影有至少一個公共點。

題解思路:
實際上就是問,是否存在一條直線K, 和所 有這些線段都相交。L是K的垂線即可。
若存在一條直線與所有線段相交,該直線必 定經過這些線段的某兩個端點(否則可以平 移或轉動使之靠上端點)。枚舉任意兩個端 點構造直線並看它是否與每條線段相交即可

AC代碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const double eps=1e-6;
const int maxn=255;
struct point{
	double x,y;
	point() : x(0),y(0) {}
	point(double xx,double yy):x(xx),y(yy){}
}f[maxn];
point operator - (point ta,point tb)
{
	return point(ta.x-tb.x,ta.y-tb.y);
}
double cross(point ta,point tb)
{
	return ta.x*tb.y-ta.y*tb.x;
}
double len(point ta)
{
	return sqrt(ta.x*ta.x+ta.y*ta.y);
}
double mult(point ta,point tb,point tc)
{
	return cross(ta-tc,tb-tc);
}
int cmp(double x)
{
	if(fabs(x)<eps) return 0;
	return x<0?-1:1;
}
int isformal(point ta,point tb,point tc,point td)
{
	int tx,ty;
	tx=cmp(mult(ta,tc,tb));
	ty=cmp(mult(ta,td,tb));
	if(tx*ty==-1) return -1;
    if(tx==0||ty==0) return 2;
	return 0;
}
int main()
{
	int t,n;
	while(cin>>t)
	{
		while(t--)
		{
			cin>>n;
			for(int i=1;i<=n;i++)
			{
				scanf("%lf%lf%lf%lf",&f[i].x,&f[i].y,&f[i+n].x,&f[i+n].y);
			}
			if(n==1||n==2)
			{
				printf("Yes!\n");
				continue;
			}
			int flag=0;
			for(int i=1;i<=2*n;i++)
			{
				for(int j=i+1;j<=2*n;j++)
				{
					if(cmp(len(f[i]-f[j]))==0) continue;
					int ans=0;
					for(int k=1;k<=n;k++)
					{
						if(isformal(f[i],f[j],f[k],f[k+n]))
					    ans++;
					    else 
					    break;
					}
					if(ans==n)
					{
						flag=1;
						break;
					}
				}
				if(flag)
				break;
			}
			if(flag==1)
			printf("Yes!\n");
			else
			printf("No!\n");
		}
	}
	return 0;
}

判斷是否規範相交還有一個模板方法就是:

double cross(const vec & ta,const vec & tb)
{
	return (ta.x*tb.y-ta.y*tb.x);
}
bool isFormalCross(point ta,point tb,point tc,point td)
{
	return cross(tb-ta,tc-ta)*cross(tb-ta,td-ta)<-eps&&
	cross(td-tc,ta-tc)*cross(td-tc,tb-tc)<-eps
}

giao辭~~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章