【题目大意】给出房子的坐标表示为(x1,x2,y)代表房子所在二维坐标系上的位置,给出路的坐标表示(rx1,rx2,ry)同样表示路在二维坐标系上的位置。然后给出n个障碍物,每个障碍物的坐标表示是(a[i].x1,a[i].x2,a[i].y),问在路上避过障碍物可以连续的看到房子的最远距离是多少。
【解题思路】先对房子和障碍物进行连线构建投影,再按照投影得到在路上的坐标进行排序,最后取即刻。
哎,说起来很简单,写起来就....T_T....各种哭爹叫娘。
首先,障碍物跟房子和路都不会是同一个纵坐标;另外,投影可能会投影在路外面....足足wa了我8次,8次啊.....
刚开始开了线段这个结构体以为要用到,后来发现其实坐标点都没什么用,有用的还是横坐标而已~~懒得改回来了~程序就显得冗长一点。
【代码】:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
#define eps 1e-9
struct Point{
double x,y;
Point(){}
Point(double a,double b){
x=a,y=b;
}
};
struct Line{
Point a,b;
Line() {}
Line(Point x,Point y){
a=x,b=y;
}
};
struct Region{
double l,r;
};
double x1,y,x2,rx1,rx2,ry,ans;
int n;
Point obl[10000],obr[10000];
Point rl,rr,hl,hr;
Region Reg[10000];
double getPoint(const Point &a,const Point &b){
if(a.x==b.x) return a.x;
return a.x+(rl.y-a.y)/((a.y-b.y)/(a.x-b.x));
}
void get_linemap(){
for (int i=0; i<n; i++){
double ll=getPoint(obl[i],hr); //连接两点做延长线求与Road的交点横坐标
double rrr=getPoint(obr[i],hl);
if(ll>rx2+eps||rrr+eps<rx1) {n--; i--; continue;} //如果左投影在路的右边,或者右投影在路的左边则跳过
if (ll>rl.x) Reg[i].l=ll; else Reg[i].l=rl.x;
if (rrr<rr.x) Reg[i].r=rrr; else Reg[i].r=rr.x;
}
return ;
}
bool cmp(const Region &a,const Region &b){
if (fabs(a.l-b.l)<eps) return a.r+eps<b.r;
else return a.l+eps<b.l;
}
void solve(){
ans=0;
sort(Reg,Reg+n,cmp);
double tmp=rx1; //表示现在的左端点
for(int i=0; i<n; i++)
{
if(Reg[i].l>tmp+eps)
{
if (ans<Reg[i].l-tmp) ans=Reg[i].l-tmp;
tmp=Reg[i].r; //更新左端点
}
else if(Reg[i].r>tmp+eps)
tmp=Reg[i].r;
}
if(tmp+eps<rx2)
if (ans<rx2-tmp) ans=rx2-tmp; //对右端点的一截进行特殊处理
return ;
}
int main(){
while (~scanf("%lf%lf%lf",&x1,&x2,&y)){
hl=Point(x1,y);
hr=Point(x2,y);
if (x1==0 && x2==0 && y==0) break;
scanf("%lf%lf%lf",&rx1,&rx2,&ry);
rl=Point(rx1,ry);
rr=Point(rx2,ry);
scanf("%d",&n);
double a,b,c;
for (int i=0; i<n; i++){
scanf("%lf%lf%lf",&a,&b,&c);
if (c+eps<ry||fabs(c-ry)<eps||c>=y+eps||fabs(c-y)<eps) {i--; n--;continue;} //判断障碍物是否在路和房子之间,障碍物不与路和房子在同意水平线上
obl[i]=Point(a,c);
obr[i]=Point(b,c);
// ob[i].Line(obl[i],obr[i]);
}
get_linemap(); //连接障碍物的左端点和房子的右端点,连接障碍物的右端点和房子的左端点,分别求出起在路上的最小范围投影。
if (n==0) ans=rx2-rx1;
else solve();
if (ans>eps) printf("%.2f\n",ans);
else printf("No View\n");
}
return 0;
}
该博客主要介绍了POJ 2704题目的解题思路,涉及计算几何问题。题目要求根据房子和路的坐标,以及多个障碍物的位置,计算避开障碍物后从路上能看到房子的最远距离。解题过程中,需要对障碍物和房子进行连线投影,并对投影结果排序。博主分享了在实现过程中遇到的困难,如障碍物和路的纵坐标不会相同,以及投影可能超出路的范围等问题,这些问题导致了多次错误。最终,博主通过简化数据结构和优化算法找到了解决方案,尽管代码因此显得较为冗长。
622

被折叠的 条评论
为什么被折叠?



