双调tsp的模板题,暑假时看没看懂,现在很好理解方程。
f[i][j]表示dis[1...i]+dis[1...j]的最短路径长度(max(i,j)之前的点全部经过且仅经过一次),f[i][j]=f[j][i],只需要计算一半即可,边界就是f[1][2]=dis(P[1],P[2]);
if(i<j-1) f[i][j]=f[i][j-1]+d[j-1][j];
if(i==j-1) f[i][j]=MIN{f[k][j-1]+d[k][j] | k<j-1 }
if(i==j) 两点相遇,只有在i==n时才能计算,f[n][n]=f[n-1][n]+d[n-1][n];
1 #include<bits/stdc++.h> 2 using namespace std; 3 struct Point 4 { 5 double x,y; 6 }P[220]; 7 double f[210][210]; 8 double d[210][210]; 9 double dis(Point A,Point B){return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));} 10 int main() 11 { 12 int n,i,j,k; 13 while(cin>>n){ 14 for(i=1;i<=n;++i) 15 cin>>P[i].x>>P[i].y; 16 for(i=1;i<=n;++i) 17 for(j=i+1;j<=n;++j) 18 d[i][j]=d[j][i]=dis(P[i],P[j]); 19 f[1][2]=d[1][2]; 20 for(j=3;j<=n;++j) 21 { 22 for(i=1;i<j-1;++i) 23 f[i][j]=f[i][j-1]+d[j-1][j]; 24 f[j-1][j]=9999999999; 25 for(k=1;k<j-1;++k) 26 f[j-1][j]=min(f[j-1][j],f[k][j-1]+d[k][j]); 27 } 28 printf("%.2f ",f[n-1][n]+d[n-1][n]); 29 } 30 return 0; 31 }