P1027 car的旅行路线
car的旅行路线
这个题关键就是
如何把每个点表示出来,其实求出四个点的坐标后,只需要把这些点连接起来,用一遍folyed求出最短路径就好了。
代码:
1 #include<cmath> 2 #include<cstdio> 3 int x[801],y[801];//x表示横坐标,y表示纵坐标 4 int ti[501];//在第i个城市中铁路单位里程价格 5 int n,s,tt,a,b;//tt表示航线单位里程价格 6 double d[501][501];//i到j的长度(花费) 7 void doit(int t1,int t2){//计算t1到t2的花费 8 d[t1][t2]=sqrt((x[t1]-x[t2])*(x[t1]-x[t2]) 9 +(y[t1]-y[t2])*(y[t1]-y[t2]));//求t1到t2的长度 10 if (((t1-1)/4)==((t2-1)/4)){//判断t1,t2是否在同一个城市内 11 d[t1][t2]=d[t1][t2]*ti[(t1-1)/4+1];//计算花费 12 }else 13 d[t1][t2]=d[t1][t2]*tt; 14 d[t2][t1]=d[t1][t2];//对称 15 return;//结束 16 } 17 int find(int t1,int t2,int t3){//找直角三角形斜边 18 //如果一边长度大于任意两边返回此边对着的点 19 if((d[t1][t2]>d[t2][t3])&&(d[t1][t2]>d[t3][t1])) return t3; 20 //t1t2对应的点为t3 21 if((d[t2][t3]>d[t1][t2])&&(d[t2][t3]>d[t3][t1])) return t1; 22 //t2t3对应的点为t1 23 if((d[t3][t1]>d[t2][t3])&&(d[t3][t1]>d[t1][t2])) return t2; 24 //t1t3对应的点为t2 25 } 26 void doit2(int t1,int t2,int t3){ 27 doit(t1,t2);//t1到t2的花费(比在同一城市) 28 doit(t2,t3);//t2到t3的花费(必在同一城市) 29 doit(t3,t1);//t3到t1的花费(必在同一城市) 30 int haha=find(t1,t2,t3);//找此直角三角形的斜边 31 //而在平行四边形中 32 //一条边的两个顶点的横(或纵)坐标的差值 33 //等于其对边两个顶点的横(或纵)坐标的差值 34 if(haha==t1){//看斜边对着的点为哪个,并求出第4个点的坐标 35 x[t3+1]=x[t3]+x[t2]-x[t1]; 36 y[t3+1]=y[t3]+y[t2]-y[t1]; 37 } 38 else if(haha==t2){ 39 x[t3+1]=x[t3]+x[t1]-x[t2]; 40 y[t3+1]=y[t3]+y[t1]-y[t2]; 41 } 42 else if(haha==t3){ 43 x[t3+1]=x[t1]+x[t2]-x[t3]; 44 y[t3+1]=y[t1]+y[t2]-y[t3]; 45 } 46 } 47 int main(){ 48 scanf("%d",&n); 49 for(;n>=1;n--){//循环运行n次 50 scanf("%d %d %d %d",&s,&tt,&a,&b); 51 //S城市数,t飞机单价,A,B序号 52 int i,j,k; 53 for(i=1;i<=401;i++)//初始化 54 for(j=1;j<=401;j++) 55 d[i][j]=100000000; 56 for(i=1;i<=s;i++){ 57 scanf("%d%d%d%d%d%d%d", 58 &x[4*i-3],&y[4*i-3],&x[4*i-2], 59 &y[4*i-2],&x[4*i-1],&y[4*i-1], 60 &ti[i]); 61 doit2(4*i-3,4*i-2,4*i-1); 62 } 63 for(i=1;i<=4*s;i++) 64 for(j=1;j<=4*s;j++) 65 doit(i,j);//计算i到j的花费 66 for(k=1;k<=4*s;k++) 67 for(i=1;i<=4*s;i++) 68 for(j=1;j<=4*s;j++) 69 if(d[k][j]+d[i][k]<d[i][j]) 70 d[i][j]=d[k][j]+d[i][k];//Floyed 71 double ans=200000000.0; 72 for(i=4*a-3;i<=4*a;i++) 73 for(j=4*b-3;j<=4*b;j++) 74 if(d[i][j]<ans) 75 ans=d[i][j];//更新最小值 76 printf("%.1lf\n",ans);//输出,并保留一位小数 77 } 78 return 0; 79 }