首页 > 代码库 > POJ 2288 Islands and Bridges 哈密尔顿路 状态压缩DP

POJ 2288 Islands and Bridges 哈密尔顿路 状态压缩DP

找最长的其实是很裸的状态压缩DP,棘手的地方是要统计数量,其实只要再来一个数组存就好。

不过代码比较长,细节要注意的地方毕较多,wa了很多发,还是要仔细啊

用递推和记忆化搜索分别写了一遍

#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <climits>#include <string>#include <iostream>#include <map>#include <cstdlib>#include <list>#include <set>#include <queue>#include <stack>using namespace std;typedef long long LL;const int maxn = 14;const int INF = INT_MAX / 3;int n,m,dist[maxn][maxn];LL v[maxn];LL f[maxn][maxn][1 << 14];LL cnt[maxn][maxn][1 << 14];void solve() {    memset(f,-1,sizeof(f));    memset(cnt,0,sizeof(cnt));    int maxstate = (1 << n) - 1; //init    for(int i = 0;i < n;i++) {        for(int j = 0;j < n;j++) if(dist[i][j]) {            int s = (1 << i) | (1 << j);            f[i][j][s] = v[i] * v[j] + v[i] + v[j];            cnt[i][j][s] = 1;        }    }    //dp    LL ans = 0,ct = 0;    for(int s = 0;s <= maxstate;s++) {        for(int i = 0;i < n;i++) if(s & (1 << i)) {            for(int j = 0;j < n;j++) if(dist[i][j] && (s & (1 << j)) && f[i][j][s] != -1) {                for(int k = 0;k < n;k++) if(dist[j][k] && !(s & (1 << k))) {                    int ns = s | (1 << k);                    LL &nowstate = f[i][j][s],&nextstate = f[j][k][ns];                    LL &nowcnt = cnt[i][j][s],&nextcnt = cnt[j][k][ns];                    LL addv = v[j] * v[k] + v[k];                    if(dist[i][k]) addv += v[i] * v[j] * v[k];                    if(nowstate + addv > nextstate) {                        nextstate = nowstate + addv;                        nextcnt = nowcnt;                    }                    else if(nowstate + addv == nextstate) {                        nextcnt += nowcnt;                    }                }                if(s == maxstate) {                    if(f[i][j][s] > ans) {                        ans = f[i][j][s];                        ct = cnt[i][j][s];                    }                    else if(f[i][j][s] == ans) {                        ct += cnt[i][j][s];                    }                }            }        }    }    if(ans == 0) cout << "0 0" << endl;    else cout << ans << " " << ct / 2 <<  endl;}int main() {    //freopen("in.txt","r",stdin);    int T; scanf("%d",&T);    while(T--) {        memset(dist,0,sizeof(dist));        scanf("%d%d",&n,&m);        for(int i = 0;i < n;i++) cin >> v[i];        for(int i = 0;i < m;i++) {            int a,b; cin >> a >> b;            a--; b--;            dist[a][b] = dist[b][a] = 1;        }        if(n == 1) cout << v[0] << " " << 1 << endl;        else solve();    }    return 0;}

  

  1 #include <cstdio>  2 #include <sstream>  3 #include <fstream>  4 #include <cstring>  5 #include <iostream>  6 #include <algorithm>  7 #include <map>  8 #include <cctype>  9 #include <ctime> 10 #include <set> 11 #include <climits> 12 #include <vector> 13 #include <queue> 14 #include <stack> 15 #include <cstdlib> 16 #include <cmath> 17 #include <string> 18 #include <list> 19  20 #define INPUT_FILE "in.txt" 21 #define OUTPUT_FILE "out.txt" 22  23 using namespace std; 24  25 typedef long long LL; 26 const int INF = INT_MAX / 2; 27  28 void setfile() { 29     freopen(INPUT_FILE,"r",stdin); 30     freopen(OUTPUT_FILE,"w",stdout); 31 } 32  33 const int maxn = 13; 34  35 int n,maxstate; 36 LL w[maxn][maxn],c[maxn]; 37 LL note[maxn][maxn][1 << 13]; 38 LL cnt[maxn][maxn][1 << 13]; 39  40 LL dfs(int prev,int now,int state) { 41     if(state == maxstate) return note[prev][now][state] = 0; 42     LL ret = -1,nret;  43     if(note[prev][now][state] != -1) { 44         return note[prev][now][state]; 45     } 46     for(int i = 0;i < n;i++) { 47         if((state & (1 << i)) == 0 && w[now][i] != -1) { 48             LL addv = w[now][i] + c[i]; 49             if(w[prev][i] != -1) addv += c[i] * c[prev] * c[now]; 50             nret = dfs(now,i,state | (1 << i)) + addv; 51             if(nret > ret) { 52                 ret = nret; 53             } 54         } 55     } 56     if(ret == -1) return -INF * 100000LL; 57     return note[prev][now][state] = ret; 58 } 59  60 LL getcount(int prev,int now,int state) { 61     if(state == maxstate) return 1; 62     if(cnt[prev][now][state] != -1) return cnt[prev][now][state]; 63     LL ret = 0; 64     for(int i = 0;i < n;i++) { 65         if((state & (1 << i)) == 0 && w[now][i] != -1) { 66             LL addv = w[now][i] + c[i]; 67             if(w[prev][i] != -1) addv += c[i] * c[prev] * c[now]; 68             if(note[prev][now][state] == note[now][i][state | (1 << i)] + addv) { 69                 ret += getcount(now,i,state | (1 << i)); 70             } 71         } 72     } 73     return cnt[prev][now][state] = ret; 74 } 75  76 int main() { 77     int T; 78     cin >> T; 79     while(T--) { 80         memset(w,-1,sizeof(w)); 81         memset(cnt,-1,sizeof(cnt)); 82         memset(note,-1,sizeof(note)); 83         int m; 84         cin >> n >> m; 85         for(int i = 0;i < n;i++) { 86             cin >> c[i]; 87         } 88         for(int i = 0;i < m;i++) { 89             int u,v; 90             cin >> u >> v; 91             u--; v--; 92             w[u][v] = w[v][u] = c[u] * c[v]; 93         } 94         maxstate = (1 << n) - 1; 95         LL ans = 0,ccnt = 0; 96         for(int i = 0;i < n;i++) { 97             for(int j = 0;j < n;j++) if(i != j && w[i][j] != -1) { 98                 LL ret = dfs(i,j,(1<<i)|(1<<j)) + w[i][j] + c[i] + c[j]; 99                 ans = max(ans,ret);100             }101         }102         for(int i = 0;i < n;i++) {    103             for(int j = 0;j < n;j++) {104                 if(note[i][j][(1 << i)|(1 << j)] + w[i][j] + c[i] + c[j] == ans) {105                     ccnt += getcount(i,j,(1<<j)|(1<<i));106                 }107             }108         }109         if(n == 1) cout << c[0] << " " << 1 << endl;110         else if(ccnt == 0) cout << "0 0" << endl;111         else cout << ans << " " << ccnt / 2 << endl;112     }113     return 0;114 }