郊区春游(状压DP水题)+ 记录路径
题目链接:
https://ac.nowcoder.com/acm/problem/16122
题目大意:
中文
具体思路:
首先对全图跑一遍floyed,然后dp[i][j]表示第i个状态在j点停下来的最短距离。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define inf 0x3f3f3f3f 5 #define LL_inf (1ll << 60) 6 const int maxn = 200+55; 7 const int mod = 1e9 + 7; 8 int sto[maxn]; 9 int dp[34000][maxn]; 10 int dis[maxn][maxn]; 11 int n,m,r; 12 void floyed() 13 { 14 for(int i=1; i<=n; i++) 15 { 16 for(int j=1; j<=n; j++) 17 { 18 for(int k=1; k<= n; k++) 19 { 20 dis[j][k]=min(dis[j][k],dis[j][i]+dis[i][k]); 21 } 22 } 23 } 24 } 25 int main() 26 { 27 // cout<<(1<<15)<<endl; 28 scanf("%d %d %d",&n,&m,&r); 29 for(int i=0; i<r; i++) 30 { 31 scanf("%d",&sto[i]); 32 } 33 for(int i=1; i<=n; i++) 34 { 35 for(int j=1; j<=n; j++) 36 { 37 if(i==j) 38 dis[i][j]=0; 39 else 40 dis[i][j]=inf ; 41 } 42 } 43 int st,ed,val; 44 for(int i=1; i<=m; i++) 45 { 46 scanf("%d %d %d",&st,&ed,&val); 47 //st--,ed--; 48 dis[st][ed]=min(dis[st][ed],val); 49 dis[ed][st]=dis[st][ed]; 50 } 51 floyed(); 52 // for(int i=0;i<n;i++){ 53 // for(int j=i;j<n;j++){ 54 // cout<<i<<" "<<j<<" "<<dis[i][j]<<endl; 55 // } 56 // } 57 memset(dp,inf,sizeof (dp) ); 58 for(int i=0; i<r; i++) 59 { 60 dp[(1<<i)][i]=0 ; 61 } 62 int maxstate=(1<<r)-1; 63 for(int i=0; i<=maxstate; i++) 64 { 65 for(int j=0; j<r; j++) 66 { 67 if((i&(1<<j))==0) 68 continue; 69 for(int k=0; k<r; k++) 70 { 71 // if(i&(1<<k)) 72 // continue; 73 dp[i^(1<<k)][k]=min(dp[i^(1<<k)][k],dp[i][j]+dis[sto[j]][sto[k]]); 74 } 75 } 76 } 77 int minn=inf ; 78 for(int i=0; i<r; i++) 79 { 80 minn=min(minn,dp[maxstate][i]); 81 } 82 printf("%d\n",minn); 83 return 0; 84 }
记录路径
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define inf 0x3f3f3f3f 5 #define LL_inf (1ll << 60) 6 const int maxn = 200 + 55; 7 const int mod = 1e9 + 7; 8 int sto[maxn]; 9 int dp[34000][maxn]; 10 int dis[maxn][maxn]; 11 int n, m, r; 12 pair<int, int> pre[(1 << 16)][(20)]; 13 void floyed() { 14 for (int i = 1; i <= n; i++) { 15 for (int j = 1; j <= n; j++) { 16 for (int k = 1; k <= n; k++) { 17 dis[j][k] = min(dis[j][k], dis[j][i] + dis[i][k]); 18 } 19 } 20 } 21 } 22 int flag=1; 23 void dfs(int sta, int pos) { 24 if (sta != -1) { 25 dfs(pre[sta][pos].first, pre[sta][pos].second); 26 if(flag){ 27 flag=0; 28 } 29 else 30 cout << sto[pre[sta][pos].second] << " "; 31 } 32 } 33 int main() { 34 // cout<<(1<<15)<<endl; 35 scanf("%d %d %d", &n, &m, &r); 36 for (int i = 0; i < r; i++) { 37 scanf("%d", &sto[i]); 38 } 39 for (int i = 1; i <= n; i++) { 40 for (int j = 1; j <= n; j++) { 41 if (i == j) 42 dis[i][j] = 0; 43 else 44 dis[i][j] = inf; 45 } 46 } 47 int st, ed, val; 48 for (int i = 1; i <= m; i++) { 49 scanf("%d %d %d", &st, &ed, &val); 50 dis[st][ed] = min(dis[st][ed], val); 51 dis[ed][st] = dis[st][ed]; 52 } 53 floyed(); 54 memset(dp, inf, sizeof(dp)); 55 for (int i = 0; i < r; i++) { 56 dp[(1 << i)][i] = 0; 57 pre[i][i] = make_pair(-1, i); 58 } 59 int maxstate = (1 << r) - 1; 60 for (int i = 0; i <= maxstate; i++) { 61 for (int j = 0; j < r; j++) { 62 if ((i & (1 << j)) == 0) 63 continue; 64 for (int k = 0; k < r; k++) { 65 if (i & (1 << k)) 66 continue; 67 if (dp[i][j] + dis[sto[j]][sto[k]] < dp[i ^ (1 << k)][k]) { 68 dp[i ^ (1 << k)][k] = dp[i][j] + dis[sto[j]][sto[k]]; 69 pre[i ^ (1 << k)][k] = make_pair(i, j); 70 } 71 } 72 } 73 } 74 int sta; 75 int minn = inf; 76 for (int i = 0; i < r; i++) { 77 if (dp[maxstate][i] < minn) { 78 minn = dp[maxstate][i]; 79 sta = i; 80 } 81 } 82 dfs(maxstate, sta); 83 return 0; 84 }