郊区春游(状压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
",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 }
原文地址:https://www.cnblogs.com/letlifestop/p/11079361.html