poj 1556 计算几何+最短路
主要是构图花了不少时间,应该一小时能够搞定的,却花了三个小时,最大的原因是初始化没有做好
说下题目,我们给每个点一个编号,然后求出每两个点之间的最短路径,肯定是直线最短。
然后为了简化,我们可以只求这个点和他后面的点的关系(因为必然可以向前走,不可能折回来再往前走才是最短的),
注意一点,不是每两个点之间都能直达的,得判断其中经过的路径有没有被墙堵住了(判断直线和线段的关系 )
判断如下
bool check(int now,int no,int next,int h)//第几行第几个,要到第几行第几个 { int i,j; for(i=now+1;i<next;i++) { for(j=0;j<6;j+=2) { if(xmult(wall[now][no],wall[i][j],wall[next][h])*xmult(wall[now][no],wall[i][j+1],wall[next][h])<eps) //遇到障碍 { // printf("J:%d k:%d (%.2lf,%.2lf) (%.2lf,%.2lf) \n",i,j,wall[i][j].x,wall[i][j].y,wall[i][j+1].x,wall[i][j+1].y); return false; } } } return true; }
图构好之后,DIJ可解,附代码
#include<stdio.h> #include<string.h> #include<math.h> #define eps 1e-8 #define val 100 #define INF 1<<25 #define zero(x) (((x)>0?(x):-(x))<eps) typedef struct {double x,y;} point; point wall[20][6]; double dis[val],map[val][val]; bool in[val]; int n,m,s,t,num; void dij(); void create_link(); double xmult(point p1,point p2,point p0) { return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } int main() { int i,j; double x; while(scanf("%d",&num)&&num!=-1) { n=num*4+1; for(i=1;i<=num;i++) { scanf("%lf",&x); wall[i][0].y=0; wall[i][5].y=10; for(j=0;j<6;j++) { wall[i][j].x=x; // printf("XX:%.2lf \n",x); } for(j=1;j<=4;j++) scanf("%lf",&wall[i][j].y); } // printf("X:%.2lf\n",wall[1][1].x); for(j=0;j<6;j++) { wall[0][j].x=0; wall[0][j].y=5; wall[num+1][j].x=10; wall[num+1][j].y=5; } create_link(); dij(); printf("%.2lf\n",dis[t]); } return 0; } void create_link() { int i,j,k,v; bool check(int ,int ,int ,int ); double dist(point ,point); s=0,t=n; for(i=0;i<=n;i++) for(j=0;j<=n;j++) map[i][j]=INF; /* printf("(%.2lf,%.2lf) (%.2lf,%.2lf) dis:%.2lf\n",wall[0][1].x,wall[0][1].y,wall[2][2].x,wall[2][2].y,dist(wall[0][1],wall[2][2])); printf("(%.2lf,%.2lf) (%.2lf,%.2lf) dis:%.2lf\n",wall[2][2].x,wall[2][2].y,wall[3][1].x,wall[3][1].y,dist(wall[2][2],wall[3][1])); printf("CHECK:%d \n",check(0,0,2,2));*/ for(i=0;i<=num;i++) for(j=1;j<=4;j++) { for(k=i+1;k<=num+1;k++) { for(v=1;v<=4;v++) if(check(i,j,k,v)) { // if((k-1)*4+v==n) printf("I:%d j:%d k:%d v:%d\n",i,j,k,v); // printf("I:%d j:%d k:%d v:%d dis:%.2lf \n",i,j,k,v,dist(wall[i][j],wall[k][v])); if(i==0) { if(k==num+1) map[s][n]=dist(wall[i][j],wall[k][v]); else map[s][(k-1)*4+v]=dist(wall[i][j],wall[k][v]); } else if(k==num+1) map[(i-1)*4+j][n]=dist(wall[i][j],wall[k][v]); else map[(i-1)*4+j][(k-1)*4+v]=dist(wall[i][j],wall[k][v]); } } } /* for(i=0;i<=n;i++) { for(j=0;j<=n;j++) if(map[i][j]==INF) printf("-1 "); else printf("%.2lf ",map[i][j]); putchar('\n'); }*/ // printf("check:%d\n", check(0,0,n,0)); } bool check(int now,int no,int next,int h) { int i,j; for(i=now+1;i<next;i++) { for(j=0;j<6;j+=2) { if(xmult(wall[now][no],wall[i][j],wall[next][h])*xmult(wall[now][no],wall[i][j+1],wall[next][h])<eps) //遇到障碍 { // printf("J:%d k:%d (%.2lf,%.2lf) (%.2lf,%.2lf) \n",i,j,wall[i][j].x,wall[i][j].y,wall[i][j+1].x,wall[i][j+1].y); return false; } } } return true; } double dist(point p,point q) { return sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y)); } void dij() { int i,j,v; double min; memset(in,false,sizeof(in)); for(i=0;i<=n;i++) dis[i]=map[s][i]; dis[s]=0; in[s]=true; for(i=0;i<n;i++) { v=-1; min=INF; for(j=0;j<=n;j++) if(!in[j]&&dis[j]<min) { min=dis[j]; v=j; } if(v==-1) return ; in[v]=true; for(j=0;j<=n;j++) if(!in[j]&&dis[j]>min+map[v][j]) dis[j]=min+map[v][j]; } }