主要是构图花了不少时间,应该一小时能够搞定的,却花了三个小时,最大的原因是初始化没有做好
说下题目,我们给每个点一个编号,然后求出每两个点之间的最短路径,肯定是直线最短。
然后为了简化,我们可以只求这个点和他后面的点的关系(因为必然可以向前走,不可能折回来再往前走才是最短的),
注意一点,不是每两个点之间都能直达的,得判断其中经过的路径有没有被墙堵住了(判断直线和线段的关系 )
判断如下
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];
}
}