hdu 3001(状压dp, 3进制)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001

由于本题中一个点最多能够访问2次,由此可以联想到3进制;

visited[i][j]表示在状态i下在点j已经做过的次数,dp[i][j]表示在状态i下到达点j走过的最小的路程,于是我们可以通过预处理得到visited[i][j]数组,然后就是一般的状态转移。

 1 /*************************************************************************
 2     > File Name: hdu3001.cpp
 3     > Author: syhjh
 4     > Created Time: 2014年03月09日 星期日 14时50分17秒
 5  ************************************************************************/
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <cstring>
 9 #include <algorithm>
10 using namespace std;
11 
12 const int inf = 0x3f3f3f3f;
13 template < class T > inline T getMIN(const T &a, const T &b)
14 {
15     return a < b ? a : b;
16 }
17 
18 int N, M;
19 int dist[12][12];
20 int State[12];
21 int dp[60000][12];  //当前状态下在某个点的值
22 int visited[60000][12]; //当前状态i下在点j已经走过的次数
23 
24 void Init()
25 {
26     State[0] = 1;
27     for (int i = 1; i <= 10; i++) {
28         State[i] = State[i - 1] * 3;
29     }
30     for (int s = 0; s <= State[10]; s++) {
31         int x = s;
32         for (int i = 0; i <= 10; i++) {
33             visited[s][i] = x % 3;
34             x /= 3;
35         }
36     }
37 }
38 
39 int getDP()
40 {
41     int ans = inf;
42     memset(dp, 0x3f, sizeof(dp));
43     for (int i = 0; i < N; i++) dp[State[i]][i] = 0;
44     for (int s = 0; s < State[N]; s++) {
45         int flag = 1; //用于标记是否所有的点都已经走过
46         for (int i = 0; i < N; i++) {
47             if (visited[s][i] == 0) flag = 0;
48             if (dp[s][i] == inf) continue;
49             for (int j = 0; j < N; j++) if (j != i) {
50                 if (visited[s][j] >= 2 || dist[i][j] == inf) continue;
51                 dp[s + State[j]][j] = getMIN(dp[s + State[j]][j], dp[s][i] + dist[i][j]);
52             }
53         }
54         if (flag) {
55             for (int i = 0; i < N; i++) {
56                 ans = getMIN(ans, dp[s][i]);
57             }
58         }
59     }
60     if (ans == inf) ans = -1;
61     return ans;
62 }
63 
64 
65 int main()
66 {
67     Init();
68     while (cin >> N >> M) {
69         memset(dist, 0x3f, sizeof(dist));
70         while (M--) {
71             int u, v, w;
72             cin >> u >> v >> w;
73             u--, v--;
74             dist[u][v] = dist[v][u] = getMIN(dist[u][v], w);
75         }
76         cout << getDP() << endl;
77     }
78     return 0;
79 }
View Code

 

posted @ 2014-03-09 15:51  ihge2k  阅读(471)  评论(0编辑  收藏  举报