「CodeVS」 2800 送外卖 (状压、TSP)
题意:原题在这
快递小哥从city 0出发去(n+1)*(n+1)城市矩阵中送快递,求来回最短时间
做法:
TSP问题,这里选用dp做法
Floyd初始化城市间的距离;
令dp[1<<i][i]=dis[0][i]; 表示先走一格,好转移
dp[s][j]表示走了j个城市,状态为s时的最小时间
注意所有循环从0开始!从0开始!从0开始!调死人qwq
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define inf 0x3ffff using namespace std; int n; int dis[20][20]; int dp[1<<20][20]; //1<<n即为pow(2,n)的位运算形式 int main() { cin>>n; for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) { cin>>dis[i][j]; } //初始化 for(int k=0;k<=n;k++) for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) { dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); } int digit=(1<<(n+1))-1; for(int s=0;s<(1<<17);s++) for(int i=0;i<17;i++) { dp[s][i]=inf; } for(int i=1;i<=n+1;i++) { dp[1<<i][i]=dis[0][i];//先走一格,好转移 } for(int s=0;s<=digit;s++) for(int i=0;i<=n;i++) { if((s|(1<<i))!=s) continue; for(int j=0;j<=n;j++) { //if(i==j) continue; dp[s|(1<<j)][j]=min(dp[s][i]+dis[i][j],dp[s|(1<<j)][j]); } } cout<<dp[digit][0]<<endl; return 0; }