HDU 5418 Victor and World (状压DP入门)
2017-03-30 16:07
477 查看
题目地址:点击打开链接
题意:
每个点都可以走多次的TSP问题:有n个点(n<=16),从点1出发,经过其他所有点至少1次,并回到原点1,使得路程最短。
思路:
给了很多重边,选最小的留下即可。任意点可能无法直接到达,所以先执行一次floyd,算出任意点对之间可达的
最短距离。
(1)先考虑穷举的方法,将2~n个这n-1个数字的所有组合情况都算一遍,复杂度是 15!=1 3076 7436 8000,
那是真的TSP了,不可能实现。
(2)上面的方法中有没有多余的计算量?有的!里面还是有贪心可以运用的地方。对于当前遍历过了哪些点,
我们只需要知道最后一个点是什么,中间的点的顺序是所所谓的,那么最后一个遍历的可以是2~n,而中间那些可以
是其他的2~n中的数。起点1的距离更新为0,接下来递推就行了。递推方法是,穷举所有的中间状态s,然后以这些状
态去穷举下一个到达的点(此点不在s中)。
状态方程是: dp[s|(1<<(u))][u]=min(dp[s][v]+g[v][u] ); s表示已经遍历过的点,v是最后那个点,u是未遍历过的
点,从j走到i。
摘自:点击打开链接
dfs或是递推都可以。
dfs:
递推:
题意:
每个点都可以走多次的TSP问题:有n个点(n<=16),从点1出发,经过其他所有点至少1次,并回到原点1,使得路程最短。
思路:
给了很多重边,选最小的留下即可。任意点可能无法直接到达,所以先执行一次floyd,算出任意点对之间可达的
最短距离。
(1)先考虑穷举的方法,将2~n个这n-1个数字的所有组合情况都算一遍,复杂度是 15!=1 3076 7436 8000,
那是真的TSP了,不可能实现。
(2)上面的方法中有没有多余的计算量?有的!里面还是有贪心可以运用的地方。对于当前遍历过了哪些点,
我们只需要知道最后一个点是什么,中间的点的顺序是所所谓的,那么最后一个遍历的可以是2~n,而中间那些可以
是其他的2~n中的数。起点1的距离更新为0,接下来递推就行了。递推方法是,穷举所有的中间状态s,然后以这些状
态去穷举下一个到达的点(此点不在s中)。
状态方程是: dp[s|(1<<(u))][u]=min(dp[s][v]+g[v][u] ); s表示已经遍历过的点,v是最后那个点,u是未遍历过的
点,从j走到i。
摘自:点击打开链接
dfs或是递推都可以。
dfs:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; const int maxn = 20; const int INF = 0x3f3f3f3f; struct node { int v, w; node() {} node(int vv, int ww): v(vv), w(ww) {} }; int dp[1<<maxn][maxn], g[maxn][maxn], n, m; void floyd() { for(int k = 0; k < n; k++) for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) g[i][j] = min(g[i][j], g[i][k]+g[k][j]); } int dfs(int S, int v) { if(dp[S][v] >= 0) return dp[S][v]; if(S == (1<<n)-1 && v == 0) return dp[S][v] = 0; int res = INF; for(int u = 0; u < n; u++) { if(!(S>>u & 1)) res = min(res, dfs(S | 1<<u, u)+g[v][u]); } return dp[S][v] = res; } int main(void) { int t; cin >> t; while(t--) { scanf("%d%d", &n, &m); for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) g[i][j] = i==j ? 0 : INF; while(m--) { int u, v, w; scanf("%d%d%d", &u, &v, &w); u--, v--; g[u][v] = min(g[u][v], w); g[v][u] = min(g[v][u], w); } floyd(); memset(dp, -1, sizeof(dp)); printf("%d\n", dfs(0, 0)); } return 0; }
递推:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 20; const int INF = 0x3f3f3f3f; int n, m, g[maxn][maxn], dp[1<<maxn][maxn]; void floyd() { for(int k = 0; k < n; k++) for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) g[i][j] = min(g[i][j], g[i][k]+g[k][j]); } int main(void) { int t; cin >> t; while(t--) { scanf("%d%d", &n, &m); for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) g[i][j] = i==j ? 0 : INF; while(m--) { int u, v, w; scanf("%d%d%d", &u, &v, &w); u--, v--; g[u][v] = min(g[u][v], w); g[v][u] = min(g[v][u], w); } floyd(); memset(dp, INF, sizeof(dp)); dp[0][0] = 0; for(int s = 0; s < 1<<n; s++) for(int v = 0; v < n; v++) if(dp[s][v] != INF) for(int u = 0; u < n; u++) dp[s|(1<<u)][u] = min(dp[s|(1<<u)][u], dp[s][v]+g[v][u]); printf("%d\n", dp[(1<<n)-1][0]); } return 0; }
相关文章推荐
- BestCoder Round #52 (div.2) HDU 5418 Victor and World (DP+状态压缩)
- 【HDOJ 5418】 Victor and World (状压dp)
- bc #52 div 2 B || hdoj 5418 Victor and World(tsp问题,状压dp)
- HDOJ 5418 Victor and World 状压DP
- hdu 5418 Victor and World(dp)
- BestCoder Round #52 (div.2) HDU 5418 Victor and World (DP+状态压缩)
- HDU 5418 Victor and World (状态压缩dp)
- hdu 5418 Victor and World 状态压缩dp,旅行商问题
- HDU 5418 Victor and World (Floyd + 状态压缩DP)
- HDU 5418 Victor and World(状态压缩路径DP或+floyd 两种方法 求 玈行商问题)经典
- 旅行商问题 TSP问题 状压dp入门 + floyd poj 3311 hdu 5418
- hdu 5418 Victor and World【状态压缩】
- HDU 5418 Victor and World(状压dp、floy最短路)
- hdu 5418 Victor and World 状态压缩dp spfa最短路 floyed最短路
- hdu 5418 Victor and World(旅行商问题)
- HDU 5418 Victor and World ( Floyed+旅行商问题)
- HDU5418——TSP变形——Victor and World
- hdu 5418 Victor and World(floyd+状压dp)
- HDU 5418 Victor and World(状压dp、最短路)
- hdu_5418_Victor and World(状压DP+Floyd)