这题确实是道水题,第一,思路并不难想,就是根据房子的右端点和障碍物的左端点判断最左边能看到房子全貌的点,再根据房子的左端点和障碍物的右端点判断最右边能看到房子全貌的点,把这些点记录下来再扫描判重,根据每一个右端点,找到一个在他右边离他最近的左端点与他的距离,如果有线段覆盖这个右端点,那么该右端点就不能在某个可视区域里面,长度为零(记得将线段的左右端点加入数组中判断!)
第二,数据比较弱,过了下面这些数据应该就没什么问题了:
2 6 6
0 15 0
3
1 2 1
3 4 1
12 13 1
1 5 5
0 10 0
1
0 15 1
2 6 6
0 15 0
3
1 2 1
3 4 1
12 13 1
2 6 6
0 15 0
4
1 2 1
3 4 1
12 13 1
1 5 2
2 6 6
0 15 0
2
0 5 3
6 15 3
2 6 6
0 15 0
2
6 10 1
0 2 1
2 6 6
0 15 0
1
2 6 7
2 6 6
0 15 0
1
2 6 7
2 6 6
0 15 0
1
4 4.5 5.5
2 6 6
0 15 0
16
0 1 3
1.5 2 3
2.5 3 3
3.5 4 3
4.5 5 3
5.5 6 3
6.5 7 3
7.5 8 3
8.5 9 3
9.5 10 3
10.5 11 3
11.5 12 3
12.5 13 3
13.5 14 3
14.5 15 3
15.5 16 3
2 6 6
0 15 0
16
0 1 .1
1.5 2 .1
2.5 3 .1
3.5 4 .1
4.5 5 .1
5.5 6 .1
6.5 7 .1
7.5 8 .1
8.5 9 .1
9.5 10 .1
10.5 11 .1
11.5 12 .1
12.5 13 .1
13.5 14 .1
14.5 15 .1
15.5 16 .1
2 6 6
0 15 0
14
0 1 3
1.5 2 3
2.5 3 3
3.5 4 3
4.5 5 3
5.5 6 3
8.5 9 3
9.5 10 3
10.5 11 3
11.5 12 3
12.5 13 3
13.5 14 3
14.5 15 3
15.5 16 3
2 6 6
0 4000000000 0
2
1 2 1
15 16 3
2 6 6
0 15 1
5
1 1.5 6
17 18 1
3 5 3
0 20 10
0 20 0.5
答案:
8.80
No View
8.80
6.70
No View
4.00
15.00
15.00
No View
No View
0.44
1.00
3999999970.00
8.00
要注意障碍物不在两条线段之间的情况!
第二,数据比较弱,过了下面这些数据应该就没什么问题了:
2 6 6
0 15 0
3
1 2 1
3 4 1
12 13 1
1 5 5
0 10 0
1
0 15 1
2 6 6
0 15 0
3
1 2 1
3 4 1
12 13 1
2 6 6
0 15 0
4
1 2 1
3 4 1
12 13 1
1 5 2
2 6 6
0 15 0
2
0 5 3
6 15 3
2 6 6
0 15 0
2
6 10 1
0 2 1
2 6 6
0 15 0
1
2 6 7
2 6 6
0 15 0
1
2 6 7
2 6 6
0 15 0
1
4 4.5 5.5
2 6 6
0 15 0
16
0 1 3
1.5 2 3
2.5 3 3
3.5 4 3
4.5 5 3
5.5 6 3
6.5 7 3
7.5 8 3
8.5 9 3
9.5 10 3
10.5 11 3
11.5 12 3
12.5 13 3
13.5 14 3
14.5 15 3
15.5 16 3
2 6 6
0 15 0
16
0 1 .1
1.5 2 .1
2.5 3 .1
3.5 4 .1
4.5 5 .1
5.5 6 .1
6.5 7 .1
7.5 8 .1
8.5 9 .1
9.5 10 .1
10.5 11 .1
11.5 12 .1
12.5 13 .1
13.5 14 .1
14.5 15 .1
15.5 16 .1
2 6 6
0 15 0
14
0 1 3
1.5 2 3
2.5 3 3
3.5 4 3
4.5 5 3
5.5 6 3
8.5 9 3
9.5 10 3
10.5 11 3
11.5 12 3
12.5 13 3
13.5 14 3
14.5 15 3
15.5 16 3
2 6 6
0 4000000000 0
2
1 2 1
15 16 3
2 6 6
0 15 1
5
1 1.5 6
17 18 1
3 5 3
0 20 10
0 20 0.5
答案:
8.80
No View
8.80
6.70
No View
4.00
15.00
15.00
No View
No View
0.44
1.00
3999999970.00
8.00
#include<stdio.h>
#include<iostream>
using namespace std;
#define SIZE 101
double eps=1e-8;
struct Line{ //记录线段起点终点和距离
double s,e,y;
}house,proper,tree[SIZE],insert[SIZE]; //house,property line,obstructions和映射线段
struct Ln{
double a,b,c;
};
Ln makeLine(double x1,double y1,double x2,double y2) //构造直线一般式:ax+by+c=0
{
Ln l;
l.a=y2-y1;
l.b=x1-x2;
l.c=x2*y1-x1*y2;
return l;
}
double abs(double n)
{
if(n<0)
return -n;
return n;
}
double points(Ln l,double y)
{
return (-l.c-l.b*y)/l.a;
}
void shelter(int n) //根据直线的一般式求出每个障碍物的映射点
{
Ln left,right;
insert[n].y=proper.y;
if(tree[n].y>house.y-eps || tree[n].y<proper.y+eps)//当障碍物不在两条线段之间的时候把它的映射改成没有用的值
{
insert[n].s=proper.s-1;
insert[n].e=proper.s-1;
}
else
{
insert[n].s=max(proper.s,points(makeLine(tree[n].s,tree[n].y,house.e,house.y),proper.y));
insert[n].e=min(proper.e,points(makeLine(tree[n].e,tree[n].y,house.s,house.y),proper.y));
}
}
int main()
{
int n,i,j;
//freopen("a.a","r",stdin); //freopen一开始没去,WA了……
while(scanf("%lf %lf %lf",&house.s,&house.e,&house.y)!=EOF)
{
if(abs(house.s)<eps && abs(house.e)<eps && abs(house.y)<eps)
break;
scanf("%lf %lf %lf",&proper.s,&proper.e,&proper.y);
double maxlength=0;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%lf %lf %lf",&tree[i].s,&tree[i].e,&tree[i].y);
for(i=0;i<n;i++)
shelter(i);
insert[n].s=proper.s; //把两个端点加入查找
insert[n++].e=proper.s;
insert[n].s=proper.e;
insert[n++].e=proper.e;
for(i=0;i<n-1;i++) //对每个右端点找最近的左端点,并判断是否被覆盖
{
if(proper.s-eps>insert[i].s)
continue;
double conti=proper.e-proper.s;
for(j=0;j<n;j++)
{
if(j==i || proper.s-eps>insert[i].s)
continue;
if(insert[j].e>insert[i].e-eps && insert[j].s<insert[i].e+eps)
conti=0;
else if(insert[j].s>insert[i].e-eps)
conti=min(conti,insert[j].s-insert[i].e);
}
maxlength=max(maxlength,conti);
}
if(maxlength<eps)
printf("No View\n");
else
printf("%.2f\n",maxlength);
}
return 0;
}