hdu 3001(状压dp, 3进制)

来源:互联网 发布:dj香烟淘宝链接 编辑:程序博客网 时间:2024/06/06 19:48

题目链接: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

 

0 0
原创粉丝点击