HDU1147 - Pick-up sticks - 计算几何(判断线段相交)

1.题目描述:

Pick-up sticks

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3056    Accepted Submission(s): 1145


Problem Description
Stan has n sticks of various length. He throws them one at a time on the floor in a random way. After finishing throwing, Stan tries to find the top sticks, that is these sticks such that there is no stick on top of them. Stan has noticed that the last thrown stick is always on top but he wants to know all the sticks that are on top. Stan sticks are very, very thin such that their thickness can be neglected.
HDU1147 - Pick-up sticks - 计算几何(判断线段相交)_第1张图片
 

Input
Input consists of a number of cases. The data for each case start with 1 ≤ n ≤ 100000, the number of sticks for this case. The following n lines contain four numbers each, these numbers are the planar coordinates of the endpoints of one stick. The sticks are listed in the order in which Stan has thrown them. You may assume that there are no more than 1000 top sticks. The input is ended by the case with n=0. This case should not be processed. 
 

Output
For each input case, print one line of output listing the top sticks in the format given in the sample. The top sticks should be listed in order in which they were thrown. 
The picture to the right below illustrates the first case from input.
 

Sample Input
 
   
5 1 1 4 2 2 3 3 1 1 -2.0 8 4 1 4 8 2 3 3 6 -2.0 3 0 0 1 1 1 0 2 1 2 0 3 1 0
 

Sample Output
 
   
Top sticks: 2, 4, 5. Top sticks: 1, 2, 3.
 

Source
University of Waterloo Local Contest 2005.09.17
 

Recommend
Eddy

2.题意概述:

n条线段,先扔的可能被后扔的覆盖掉(如果后扔的筷子与前面的筷子相交则覆盖掉),求在最顶端没有被覆盖的条数

3.解题思路:

对n条暴力的话,准超时,但是注意到p是1000,因此就需要考虑到p。
判断线段相加,假设一个点在线段的左边,则点与线段的叉积为负,如果存在一条线段跨越这条线段,则与这点对应的点在线段的右边,它的叉积为正,这两个叉积相乘为负。但是,注意的是,要以这两条线段分别为基线段,乘积同时都要小于0才能说明相交。
解决TLE核心部分:
肯定会拿n条线段一次搜索,与之比较的是那些没有被覆盖的线段,对于每一个i线段,与未被覆盖的线段(用一个数组保存着)比较,相交了,则不管这条线段了,不相交,则继续保存。

4.AC代码:

#include 
#include 
#define maxn 100010
using namespace std;
struct node
{
	double x1, y1, x2, y2;
	int id;
}p[maxn], ans[maxn];

double xplus(double x1, double y1, double x2, double y2)
{
	return x1 * y2 - x2 * y1;
}
int judge(node a, node b)
{
	double tmp1 = xplus(a.x2 - a.x1, a.y2 - a.y1, b.x1 - a.x1, b.y1 - a.y1);
	double tmp2 = xplus(a.x2 - a.x1, a.y2 - a.y1, b.x2 - a.x1, b.y2 - a.y1);
	double tmp3 = xplus(b.x2 - b.x1, b.y2 - b.y1, a.x1 - b.x1, a.y1 - b.y1);
	double tmp4 = xplus(b.x2 - b.x1, b.y2 - b.y1, a.x2 - b.x1, a.y2 - b.y1);
	return tmp1 * tmp2 <= 0 && tmp3 * tmp4 <= 0 ? 0 : 1;
}
int main()
{
	int n;
	while (scanf("%d", &n) != EOF && n)
	{
		for (int i = 0; i < n; i++)
		{
			scanf("%lf%lf%lf%lf", &p[i].x1, &p[i].y1, &p[i].x2, &p[i].y2);
			p[i].id = i + 1;
		}
		int cnt = 0;
		for (int i = 0; i < n; i++)
		{
			int cnt1 = 0;
			for (int j = 0; j < cnt; j++)
				if (judge(p[i], ans[j]))
					ans[cnt1++] = ans[j];
			ans[cnt1++] = p[i];
			cnt = cnt1;
		}
		printf("Top sticks: ");
		for (int i = 0; i < cnt; i++)
			if (i == 0)
				printf("%d", ans[i].id);
			else
				printf(", %d", ans[i].id);
		printf(".\n");
	}
    return 0;
}

你可能感兴趣的:(计算几何)