首先,让我骂一句那没事找事的Car
还取一个那么奇怪的名字
看到这个题,恕我直言,我们明显可以看出这是一道图的最短路问题。由于这个题的数据范围很小(s只有100),所以在这里我们选取时间复杂度为O(n^3)的Floyd主要是好写。
还取一个那么奇怪的名字
看到这个题,恕我直言,我们明显可以看出这是一道图的最短路问题。由于这个题的数据范围很小(s只有100),所以在这里我们选取时间复杂度为O(n^3)的Floyd主要是好写。
相信大家都想得到这些,其实这道题最大的难点在预处理所以我刚才说了一大堆废话,针对他给出的每个城市,我们应该如何处理呢?
首先是读入
1 int a,b; 2 scanf("%d%d%d%d",&n,&tf,&a,&b); 3 for(int i=1;i<=4*n;i++) 4 for(int j=1;j<=4*n;j++) 5 e[i][j]=inf; 6 for(int i=1;i<=n;i++) 7 { 8 for(int j=1;j<=6;j++) 9 scanf("%d",wz[i]+j); 10 for(int j=1;j<=5;j+=2) 11 { 12 wz[i][7]+=wz[i][j]; 13 wz[i][8]+=wz[i][j+1]; 14 } 15 scanf("%d",wz[i]+9);
这里用了一个wz[][]数组,wz[i][j](j=1,3,5,7)表示第i座城市的四个点的横坐标,wz[i][j](j=2,4,6,8)表示第i座城市的四个点的纵坐标,而j=9则是路费。其中wz[i][7]与wz[i][8]是要去计算的。
而怎么算呢?我们可以得到一个公式xd=xa+xb-xc。 (y类似)(我们可以知道,已知的三点肯定是一个直角三角形,而(xa,ya)是TA的直角顶点,(xd,yd)便是TA所对的点。公式证明留给读者去思考。提示:利用两对角线交点是中点,然后使用中点坐标公式。)但我们还需要知道谁是直角顶点,这里很明显可以利用勾股定理求解。(当然还可以使用斜率乘积等于-1,但作者血与泪的教训还是建议你不要尝试。也可能是我太菜了)计算代码
1 double tp[3]; 2 int tp2=inf,tp3; 3 tp[0]=dist1(wz[i][4],wz[i][6],wz[i][3],wz[i][5]); 4 tp[1]=dist1(wz[i][2],wz[i][6],wz[i][1],wz[i][5]); 5 tp[2]=dist1(wz[i][2],wz[i][4],wz[i][1],wz[i][3]); 6 if(tp[0]+tp[1]==tp[2]){//我在之前把wz[i][7]处理成wz[i][1,3,5]的和, 7 //这里直接减两倍横纵坐标 8 wz[i][7]-=2*wz[i][5];wz[i][8]-=2*wz[i][6]; 9 } 10 else if(tp[1]+tp[2]==tp[0]){ 11 wz[i][7]-=2*wz[i][1];wz[i][8]-=2*wz[i][2]; 12 } 13 else if(tp[0]+tp[2]==tp[1]){ 14 wz[i][7]-=2*wz[i][3];wz[i][8]-=2*wz[i][4]; 15 } 16 }
这是dis1函数
double dist(int a,int b,int c,int d){ return sqrt((a-b)*(a-b)*1.0+1.0*(c-d)*(c-d)); }
然后枚举构造某城市之间飞机场的边。(这里我把城市里的每个顶点当一个点)
1 for(int i=1;i<=n;i++) 2 { 3 for(int j=1;j<=4;j++) 4 for(int k=j;k<=4;k++) 5 { 6 int u=(i-1)*4+j,v=(i-1)*4+k;//记得减一 7 double dis=dist(wz[i][j*2-1],wz[i][k*2-1],wz[i][j*2],wz[i][k*2]); 8 e[u][v]=e[v][u]=dis*wz[i][9]; 9 } 10 }
dist函数(与dist1的唯一区别就是开了根号)
1 double dist(int a,int b,int c,int d){ 2 return sqrt((a-b)*(a-b)*1.0+1.0*(c-d)*(c-d)); 3 }
接下来便是城市间最短距离的代码
1 for(int i=1;i<=n;i++) 2 for(int j=1;j<=n;j++) 3 if(i!=j){//关键!!!作者调了一小时(┬_┬) 4 for(int k=1;k<=4;k++) 5 for(int l=1;l<=4;l++) 6 { 7 int u=(i-1)*4+k,v=(j-1)*4+l; 8 double dis=dist(wz[i][k*2-1],wz[j][l*2-1],wz[i][k*2],wz[j][l*2]); 9 e[u][v]=dis*tf; 10 } 11 }
然后便是我们期待已久的Floyd
for(int k=1;k<=n*4;k++) for(int i=1;i<=n*k;i++) for(int j=1;j<=n*4;j++) if(e[i][j]>e[i][k]+e[k][j]) e[i][j]=e[i][k]+e[k][j];
最后枚举起点终点,找到最短路
1 ouble ans=inf; 2 for(int i=(a-1)*4+1;i<=a*4;i++) 3 for(int j=(b-1)*4+1;j<=b*4;j++) 4 ans=min(ans,e[i][j]); 5 printf("%.1lf",ans);
是不是很简单?
害我调了半天,万恶的Car最后给出完整代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=100005,maxm=500005,inf=0x3f3f3f3f; 4 double e[1005][1005]; 5 int wz[1005][11]; 6 int n,tf; 7 double dist(int a,int b,int c,int d){ 8 return sqrt((a-b)*(a-b)*1.0+1.0*(c-d)*(c-d)); 9 } 10 double dist1(int a,int b,int c,int d){ 11 return (a-b)*(a-b)*1.0+1.0*(c-d)*(c-d); 12 } 13 int main() 14 { 15 int t; 16 cin>>t; 17 while(t--) 18 { 19 int a,b; 20 scanf("%d%d%d%d",&n,&tf,&a,&b); 21 for(int i=1;i<=4*n;i++) 22 for(int j=1;j<=4*n;j++) 23 e[i][j]=inf; 24 for(int i=1;i<=n;i++) 25 { 26 for(int j=1;j<=6;j++) 27 scanf("%d",wz[i]+j); 28 for(int j=1;j<=5;j+=2) 29 { 30 wz[i][7]+=wz[i][j]; 31 wz[i][8]+=wz[i][j+1]; 32 } 33 scanf("%d",wz[i]+9); 34 double tp[3]; 35 int tp2=inf,tp3; 36 tp[0]=dist1(wz[i][4],wz[i][6],wz[i][3],wz[i][5]); 37 tp[1]=dist1(wz[i][2],wz[i][6],wz[i][1],wz[i][5]); 38 tp[2]=dist1(wz[i][2],wz[i][4],wz[i][1],wz[i][3]); 39 if(tp[0]+tp[1]==tp[2]){ 40 wz[i][7]-=2*wz[i][5];wz[i][8]-=2*wz[i][6]; 41 } 42 else if(tp[1]+tp[2]==tp[0]){ 43 wz[i][7]-=2*wz[i][1];wz[i][8]-=2*wz[i][2]; 44 } 45 else if(tp[0]+tp[2]==tp[1]){ 46 wz[i][7]-=2*wz[i][3];wz[i][8]-=2*wz[i][4]; 47 } 48 } 49 for(int i=1;i<=n;i++) 50 { 51 for(int j=1;j<=4;j++) 52 for(int k=j;k<=4;k++) 53 { 54 int u=(i-1)*4+j,v=(i-1)*4+k; 55 double dis=dist(wz[i][j*2-1],wz[i][k*2-1],wz[i][j*2],wz[i][k*2]); 56 e[u][v]=e[v][u]=dis*wz[i][9]; 57 } 58 } 59 for(int i=1;i<=n;i++) 60 for(int j=1;j<=n;j++) 61 if(i!=j){ 62 for(int k=1;k<=4;k++) 63 for(int l=1;l<=4;l++) 64 { 65 int u=(i-1)*4+k,v=(j-1)*4+l; 66 double dis=dist(wz[i][k*2-1],wz[j][l*2-1],wz[i][k*2],wz[j][l*2]); 67 e[u][v]=dis*tf; 68 } 69 } 70 for(int k=1;k<=n*4;k++) 71 for(int i=1;i<=n*k;i++) 72 for(int j=1;j<=n*4;j++) 73 if(e[i][j]>e[i][k]+e[k][j]) 74 e[i][j]=e[i][k]+e[k][j]; 75 double ans=inf; 76 for(int i=(a-1)*4+1;i<=a*4;i++) 77 for(int j=(b-1)*4+1;j<=b*4;j++) 78 ans=min(ans,e[i][j]); 79 printf("%.1lf",ans); 80 } 81 return 0; 82 }