码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2014-07-25 13:52:51      阅读:265      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   os   io   for   re   c   

找最长的其实是很裸的状态压缩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 }

POJ 2288 Islands and Bridges 哈密尔顿路 状态压缩DP,布布扣,bubuko.com

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

标签:style   blog   color   os   io   for   re   c   

原文地址:http://www.cnblogs.com/rolight/p/3867620.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!