您的位置:首页 > 其它

UVa 248 Cutting Corners <计算几何+SPFA>

2017-11-03 16:58 351 查看
题目

题目大意:给定起点坐标和终点坐标,以及一些矩形区域的三个点坐标,求起点到终点的最短路径长度(路径不能穿过矩形矩形区域)。

分析:容易想到的是,将所有矩形的四个角以及起点和终点看做节点,若两个节点之间的连线不跨过任何矩形区域,则在此两节点间加一条边,边权即距离,如此建图后求最短路径就好了。需要注意的是,在矩形内部的节点应当删去,另外,因为我们判断是否跨过矩形是判断此线段与矩形的四条边是否规范相交,有可能此条线段是矩形的对角线,所以我们人为为每个矩形添加两条对角线,就可以解决这个问题了。

(这道题1A,开心~。。)

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <bitset>
#include <queue>
#define V Point

using namespace std;

const double eps=1e-7;
const double INF=9999.0;
const  int MAXN=100;

struct Point;

struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
V operator -(Point p){
return Point(x-p.x,y-p.y);
}
Point operator +(V v){
return Point(x+v.x,y+v.y);
}
};

double dis(V v){
return sqrt(v.x*v.x+v.y*v.y);
}

int dblcmp(double x){
return fabs(x)<eps?0:(x>0?1:-1);
}

double det(V v1,V v2){
return v1.x*v2.y-v1.y*v2.x;
}

double dot(V v1,V v2){
return v1.x*v2.x+v1.y*v2.y;
}

bool cross(Point a,Point b,Point c,Point d){
return (dblcmp(det(b-a,c-a))^dblcmp(det(b-a,d-a)))==-2&&
(dblcmp(det(d-c,a-c))^dblcmp(det(d-c,b-c)))==-2;
}

bool rightAngle(Point a,Point b,Point c){
return 0==dblcmp(dot(b-a,c-a));
}

struct Segment{
Point p1,p2;
Segment(){}
Segment(Point _p1,Point _p2):p1(_p1),p2(_p2){}
bool onSegment(Point& p){
return dblcmp(det(p1-p,p2-p))==0&&
p.x>=min(p1.x,p2.x)&&p.x<=max(p1.x,p2.x)&&
p.y>=min(p1.y,p2.y)&&p.y<=max(p1.y,p2.y);
}
bool intersection(Point a,Point b){
return cross(p1,p2,a,b);
}
};

struct House{
Point p[4];
Segment s[6];
double area;
House(){}
House(Point *pp){
for(int i=0;i<3;++i){
if(rightAngle(pp[i],pp[(i+1)%3],pp[(i+2)%3])){
p[0]=pp[(i+1)%3];
p[1]=pp[i];
p[2]=pp[(i+2)%3];
p[3]=p[0]+(p[2]-p[1]);
area=det(p[1]-p[0],p[3]-p[0]);
break;
}
}
for(int i=0;i<4;++i){
s[i]=Segment(p[i],p[(i+1)%4]);
}
s[4]=Segment(p[0],p[2]);
s[5]=Segment(p[1],p[3]);
}
bool inHouse(Point pp){
bool flag=true;
for(int i=0;i<4;++i){
if(s[i].onSegment(pp)){
flag=false;
break;
}
}
double areaTemp=0.0;
for(int i=0;i<4;++i){
areaTemp+=fabs(det(p[i]-pp,p[(i+1)%4]-pp));
}
return dblcmp(areaTemp/2.0-area)==0&&flag;
}
};

House house[30];
Point point[MAXN];
int n,t;
double map[MAXN][MAXN];
double dist[MAXN];
int p_num;
Point start,endp;

void buildG(){
p_num=0;
point[p_num++]=start;
for(int i=0;i<n;++i){
for(int j=0;j<4;++j){
int k;
for(k=0;k<n;++k){

4000
if(i==k) continue;
if(house[k].inHouse(house[i].p[j])) break;
}
if(k==n) point[p_num++]=house[i].p[j];
}
}
point[p_num++]=endp;
for(int i=0;i<p_num;++i){
dist[i]=INF;
for(int j=i+1;j<p_num;++j){
map[i][j]=map[j][i]=INF;
bool flag=true;
for(int k=0;k<n&&flag;++k){
for(int v=0;v<6;++v){
if(house[k].s[v].intersection(point[i],point[j])){
flag=false;
break;
}
}
}
if(flag) map[i][j]=map[j][i]=dis(point[i]-point[j]);
}
}
}

void solve(){
bitset<MAXN> vis;
queue<int> q;
q.push(0);
dist[0]=0;
vis[0]=1;
while(!q.empty()){
int id=q.front();
q.pop();
vis[id]=0;
for(int i=0;i<p_num;++i){
if(dist[i]>dist[id]+map[id][i]){
dist[i]=dist[id]+map[id][i];
if(!vis[i]){
vis[i]=1;
q.push(i);
}
}
}
}
if(t>1) putchar('\n');
printf("Scenario #%d\n   route distance: %.2lf\n",t++,dist[p_num-1]);
}

int main(){
t=1;
while(scanf("%d",&n),n!=-1){
double x1,x2,y1,y2;
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
start=Point(x1,y1);
endp=Point(x2,y2);
Point pArray[3];
for(int i=0;i<n;++i){
for(int i=0;i<3;++i){
scanf("%lf %lf",&x1,&y1);
pArray[i]=Point(x1,y1);
}
house[i]=House(pArray);
}
buildG();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  uva