RLJ黑书p13页例题2
书上讲的非常清楚了,不再说了
只是注意线段相交的情况要排除一个点在线段上的情况。
还好1Y,这种题目WA了就注定悲剧。计算几何之类的要查好半天的。
题目地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2881
2881: [Ceoi2000] LandsScape
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 14 Solved: 5
[ Submit][ Status][ Discuss]
Description
话说rins操作技术太无下限了,出门装手一抽就买了2个鞋子,结果没钱了
…
于是rins一路被压榨,走上上爆塔,走下下路崩,无奈之下他硬着头皮来到了中路,然后就被pcx虐残了..rins发现自己只有-1滴血
,
万幸自己无下限
..
于是掉头就跑,奔到了野区的山岭上,xx紧随其后,带着1000米高精准爆菊神器准备收了这FB。不过此时天色已晚,pcx视力不太好,只有有光的地方才能被他打到,已知天空高度为sky,有t个一闪一闪的小星星位于不同位置,如果山上某一点与星星i的连线不穿过山上其他点或刚好与山整条线重合,则称星星i可以照亮该点,rins开了疾风步,可以躲在任意一点,那么pcx是否能爆了rins,得到fb呢?如果能,则至少要利用几个星星呢?
Input
第一行
sky
第二行
t
第
3
到
3+t-1
行
每行一个数,第
i
个星星的横坐标,保证星星横坐标已从小到大排好
第
3+t
行
n
接下来
n
行
每行两个数,表示山的转折点的纵坐标和横坐标
,保证横坐标已从小到大排好
Output
如果可以虐死
rins
,则输出最少利用的星星个数;
否则输出“
Shit..I can't see rins...
”不包括引号。
Sample Input
100
3
2 7 14
9
10 0
80 3
10 5
70 8
50 10
40 12
20 13
90 14
40 17
3
2 7 14
9
10 0
80 3
10 5
70 8
50 10
40 12
20 13
90 14
40 17
Sample Output
3
#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define eps 1e-8
const double pi=acos(-1.0);
struct point { double x,y; };
struct line { point a,b ; };
int sig(double k)
{
if(fabs(k)<eps)
return 0;
return (k>0)?1:-1;
}
double det(double x1, double y1, double x2, double y2)
{
return x1 * y2 - x2 * y1;
}
double xmult(point p0,point p1,point p2)
{
return det(p1.x-p0.x,p1.y-p0.y,p2.x-p0.x,p2.y-p0.y);
}
double dotdet(double x1,double y1,double x2,double y2)
{
return x1*x2+y1*y2;
}
double dot(point p0, point p1, point p2)
{
return dotdet(p1.x-p0.x,p1.y-p0.y,p2.x-p0.x,p2.y-p0.y);
}
int between(point p0,point p1, point p2)
{
return sig(dot(p0,p1,p2));
}
int intersect1(point a, point b, point c, point d)
{
double s1, s2, s3, s4;
int d1 = sig(s1 = xmult(a, b, c));
int d2 = sig(s2 = xmult(a, b, d));
int d3 = sig(s3 = xmult(c, d, a));
int d4 = sig(s4 = xmult(c, d, b));
if ((d1^d2) == -2 && (d3^d4) == -2)
{
return 1;
}
// if (d1 == 0 && between(c, a, b) <= 0) return 2;
// if (d2 == 0 && between(d, a, b) <= 0) return 2;
// if (d3 == 0 && between(a, c, d) <= 0) return 2;
// if (d4 == 0 && between(b, c, d) <= 0) return 2;
return 0;
}
int parallel(const line &u,const line &v)
{
return sig((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x))==0;
}
struct data
{
int l,r;
int del;
}a[110];
point st[110],hi[110];
int t,n;
double sk;
bool cmp(data a,data b)
{
if(a.del!=b.del)
return a.del<b.del;
if(a.l!=b.l)
return a.l<b.l;
}
int main()
{
while(~scanf("%lf",&sk))
{
scanf("%d",&t);
for(int i=0;i<t;i++)
{
scanf("%lf",&st[i].x);
st[i].y=sk;
}
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lf%lf",&hi[i].y,&hi[i].x);
bool jud=0;
for(int i=0;i<n;i++)
{
a[i].l=110;
a[i].r=-1;
a[i].del=0;
for(int j=0;j<t;j++)
{
bool ok=1;
for(int k=1;k<n;k++)
{
if(intersect1(st[j],hi[i],hi[k-1],hi[k]))
{
ok=0;
break;
}
}
if(ok)
{
a[i].l=min(a[i].l,j);
a[i].r=max(a[i].r,j);
}
}
if(a[i].l==110 && a[i].r==-1)
{
jud=1;
break;
}
}
if(jud)
printf("Shit..I can't see rins...\n");
else
{
int tmp=n;
//先把包含其他区间的大区间删掉
for(int i=0;i<n;i++)
{
if(a[i].del==1) continue;
for(int j=0;j<n;j++)
{
if(j==i) continue;
if(a[j].del==1) continue;
if(a[j].l<=a[i].l && a[j].r>=a[i].r)
a[j].del=1;
}
}
sort(a,a+n,cmp);
int ans=1;
int ll=a[0].r;
for(int i=0;i<n;i++)
{
if(a[i].del==1) break;
if(a[i].l>ll)
ans++,ll=a[i].r;
}
printf("%d\n",ans);
}
}
return 0;
}