题目描述:
一个人往平面上扔木条(看做线段),告诉你扔的位置(两个端点的坐标),后扔的可能会把以前扔的覆盖掉。扔完n个后,问你没有被覆盖的木条有哪些。
解题报告:
每扔一个,从上一次扔后的顶端木条开始遍历(不超过1000个),如果被刚扔的覆盖了(相交),就删掉这个顶端木条。遍历完后,注意刚扔的木条肯定也是顶端木条,加入顶端木条集合。
复杂度:扔n个,但是顶端木条不超过1000个,所以是O(1000*n)
代码如下:
#include<iostream>
#include<cmath>
using namespace std;
struct pint
{
double x,
y;
};
int eps(double xx)
{
if (fabs(xx)
<= 0.00001) return 0;
else if (xx
> 0) return 1;
else return
-1;
}
double direction(pint p1, pint p2, pint p3)
{
return (p3.x
- p1.x) * (p2.y - p1.y) - (p2.x - p1.x) * (p3.y - p1.y);
}
bool online(pint p1, pint p2, pint p3)
{
return (p3.x
>= min(p1.x, p2.x)
&& p3.x <= max(p1.x,
p2.x) && p3.y >=
min(p1.y, p2.y) && p3.y
<= max(p1.y, p2.y));
}
bool insect(pint p1, pint p2, pint p3, pint p4)
{
double d1 =
direction(p3, p4, p1);
double d2 =
direction(p3, p4, p2);
double d3 =
direction(p1, p2, p3);
double d4 =
direction(p1, p2, p4);
if (eps(d1)
* eps(d2) < 0 &&
eps(d3) * eps(d4) < 0) return true;
else if
(eps(d1) == 0 && online(p3, p4,
p1)) return true;
else if
(eps(d2) == 0 && online(p3, p4,
p2)) return true;
else if
(eps(d3) == 0 && online(p1, p2,
p3)) return true;
else if
(eps(d4) == 0 && online(p1, p2,
p4)) return true;
return
false;
}
struct line
{
pint a,
b;
int
id;
}x[1010][2], temp;
int n, cnt, from, to, len;
int main()
{
while(scanf("%d", &n)
&& n)
{
cnt = 0;
for(int i = 0; i < n; i++)
{
scanf("%lf%lf%lf%lf", &temp.a.x,
&temp.a.y, &temp.b.x,
&temp.b.y);
temp.id = i + 1;
from = i % 2, to = (i + 1) % 2, len = cnt; cnt = 0;
for(int j = 0; j < len; j++)
if (!insect(temp.a, temp.b, x[j][from].a, x[j][from].b))
x[cnt++][to] = x[j][from];
x[cnt++][to] = temp;
}
printf("Top sticks: %d", x[0][to].id);
for(int i = 1; i < cnt; i++)
printf(", %d", x[i][to].id);
printf(".\n");
}
return
0;
}
加载中,请稍候......