POJ - 3311 - Hie with the Pie(狀壓DP)
阿新 • • 發佈:2019-04-03
space stdout tin while type iostream scanf lse min
【題目描述】
給你一個n個城市的圖,城市1~n標號,問從0點把所有城市都走一遍,且只走一遍,再回到0的最短路。
n <= 10.
【題目解析】
先求出任意兩個城市的最短路。
然後用 dp[i][j] 表示走過的城市的狀態為 i ,到達的城市為 j 的最短路。
那麽對於dp[i][j] = max(dp[i][j], dp[i^(1<<(j-1))][k] + dis[k][j] )(枚舉所有 k 點,用 k 點的狀態和從 k 點走到 j 點的距離來更新)
邊界條件是如果 i == 1<<(j-1),即這個狀態只經過了 j 這個城市,此時dp[i][j] = dis[0][j]。
最後計算答案的時候不要忘了回到0點。
#include <iostream> #include <cstdio> #include <cstdlib> #include <queue> #include <algorithm> #define FOPI freopen("in.txt", "r", stdin); #define FOPO freopen("out.txt", "w", stdout); using namespace std; typedef long long LL; constint inf = 0x3f3f3f3f; const int maxn = 10 + 2; int n; int dp[1<<maxn][maxn]; int dis[maxn][maxn]; int main() { while(~scanf("%d", &n) && n) { for (int i = 0; i <= n; i++) for (int j = 0; j <= n; j++) scanf("%d", &dis[i][j]);for (int k = 0; k <= n; k++) for (int i = 0; i <= n; i++) for (int j = 0; j <= n; j++) dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]); for (int i = 0; i < (1 << n); i++) for (int j = 1; j <= n; j++) if (i == (1<<(j-1))) dp[i][j] = dis[0][j]; else dp[i][j] = inf; for (int i = 0; i < (1 << n); i++) for (int j = 1; j <= n; j++) { int s = 1 << (j-1); if (i & s) { if (i == s) continue; for (int k = 1; k <= n; k++) if (k != j && (i & (1<<(k-1)))) dp[i][j] = min(dp[i][j], dp[i^s][k] + dis[k][j]); } } int ans = inf; for (int i = 1; i <= n; i++) ans = min(ans, dp[(1<<n)-1][i] + dis[i][0]); printf("%d\n", ans); } }
POJ - 3311 - Hie with the Pie(狀壓DP)