Hie with the Pie POJ - 3311 狀態壓縮

感覺自己學狀壓DP先做這題比較正確。。。

模型比較簡單。

因爲是可以多次經過同一個地方,所以先用floyd鬆弛出任意兩點間最短距離。

然後枚舉狀態跑答案。

因爲還要回到起點, 所以答案要加上mp[i][0]

#include <cstdio>
#include <iostream>
#include <cstring>
#define inf 0x3f3f3f3f
#define ms(x) memset(x, 0, sizeof(x))
#define ll long long
using namespace std;
const int N = 1<<15;
const int mod = 1e9+7;
int n, mp[12][12];
bool vis[12];
int dp[N][15];
int ans;
int main() {
    while(scanf("%d", &n)!=EOF) {
        if(n==0) break;
        for(int i=0; i<=n; i++) {
            for(int j=0; j<=n; j++) {
                scanf("%d", &mp[i][j]);
            }
        }
        for(int k=0;k<=n;k++){
            for(int i=0;i<=n;i++){
                for(int j=0;j<=n;j++){
                    if(i==j) continue;
                    if(mp[i][j]>mp[i][k]+mp[k][j]){
                        mp[i][j] = mp[i][k]+mp[k][j];
                    }
                }
            }
        }
        int m = (1<<n);
        for(int S = 0; S<m; S++){
            for(int i=1;i<=n;i++){
                if(S == (1<<(i-1))){
                    dp[S][i] = mp[0][i];
                }
                else if(S & (1<<(i-1)) ){
                    dp[S][i] = inf;
                    for(int j=1;j<=n;j++){
                        if(S & (1<<(j-1))  && j!=i){
                            dp[S][i] = min(dp[S][i], dp[S^(1<<(i-1))][j] + mp[j][i]); //  這個^用的就很靈性
                        }                                      // 因爲S的第(i-1)爲1,所以異或後該位就變成了0
                    }
                }
            }
        }
        int ans = 1<<30;
        for(int i=1;i<=n;i++){
            ans = min(ans, dp[m-1][i] + mp[i][0]);
        }
        printf("%d\n", ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章