首页 > 代码库 > HDU 3001 Travelling 状态DP

HDU 3001 Travelling 状态DP

TSP问题,不懂就是每个点最多访问两次,最少访问一次。

所以,我们可以用三进制来当做状态。

这个题练习了一下三进制……0、1、2

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cmath>
 6 #include <algorithm>
 7 #include <string>
 8 #include <queue>
 9 #include <stack>
10 #include <vector>
11 #include <map>
12 #include <set>
13 #include <functional>
14 #include <time.h>
15 
16 using namespace std;
17 
18 const int INF = 1<<30;
19 
20 int Matrix[15][15];
21 int base[70000][15]; //base[i][j]表示 数字i从右边第j位起的三进制值
22 int dp[70000][15];
23 int thr[20];
24 int n, m;
25 
26 inline bool check(int x) { //判断是否是最终状态
27     for (int i = 0; i < n; i++) if (!base[x][i]) //如果某一位是0则不是
28         return false;
29     return true;
30 }
31 
32 inline void update(int st, int u, int v) { //更新状态
33     int &now = dp[st+thr[v]][v];
34     if (now<0) now = dp[st][u]+Matrix[u][v];
35     else now = min(now, dp[st][u]+Matrix[u][v]);
36 }
37 
38 void init() {
39     thr[0] = 1;
40     for (int i = 1; i < 20; i++)
41         thr[i] = thr[i-1]*3;
42     for (int i = 0; i < 70000; i++) {
43         int j = i, k = 0;
44         while (j) {
45             base[i][k++] = j%3;
46             j /= 3;
47         }
48     }
49 }
50 
51 void input() {
52     memset(Matrix, -1, sizeof(Matrix));
53     for (int i = 0; i < m; i++) {
54         int x, y, c;
55         scanf("%d%d%d", &x, &y, &c);
56         x--; y--;
57         if (-1==Matrix[x][y]) Matrix[x][y] = Matrix[y][x] = c;
58         else Matrix[x][y] = Matrix[y][x] = min(Matrix[x][y], c);
59     }
60 }
61 
62 void solve() {
63     memset(dp, -1, sizeof(dp));
64     for (int i = 0; i < n; i++)
65         dp[thr[i]][i] = 0;
66     for (int i = 1; i < thr[n]; i++) {
67         for (int u = 0; u < n; u++) if (dp[i][u]>-1) { //此状态可达
68             for (int v = 0; v < n; v++) if (u!=v && base[i][v]<2 && Matrix[u][v]>-1){ //可以转移到下一个状态
69                 update(i, u, v); //更新下一个状态
70             }
71         }
72     }
73 
74     int ans = -1;
75     for (int i = 0; i < thr[n]; i++) if (check(i)) {
76         for (int j = 0; j < n; j++) if (-1 < dp[i][j]) {
77             ans = ans>-1 ? min(ans, dp[i][j]) : dp[i][j];
78         }
79     }
80     printf("%d\n", ans);
81 }
82 
83 int main() {
84     #ifdef Phantom01
85         freopen("HDU3001.txt", "r", stdin);
86     #endif //Phanaom01
87 
88     init();
89     while (scanf("%d%d", &n, &m)!=EOF) {
90         input();
91         solve();
92     }
93 
94     return 0;
95 }
HDU3001