Poj 2074 Line of Sight

这题确实是道水题,第一,思路并不难想,就是根据房子的右端点和障碍物的左端点判断最左边能看到房子全貌的点,再根据房子的左端点和障碍物的右端点判断最右边能看到房子全貌的点,把这些点记录下来再扫描判重,根据每一个右端点,找到一个在他右边离他最近的左端点与他的距离,如果有线段覆盖这个右端点,那么该右端点就不能在某个可视区域里面,长度为零(记得将线段的左右端点加入数组中判断!)
要注意障碍物不在两条线段之间的情况!

第二,数据比较弱,过了下面这些数据应该就没什么问题了:
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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值