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 }

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

时间: 2024-12-28 23:30:14

POJ 2288 Islands and Bridges 哈密尔顿路 状态压缩DP的相关文章

poj 2280 Islands and Bridges 哈密尔顿路 状压dp

题目链接 题意 给定一个\(N\)个点的无向图,求一条哈密尔顿路径\(C_1C_2...C_n\),使其\(value\)最大. \(value\)的计算方式如下:\[\begin{aligned}value&=\sum_{i=1}^{n}C_i\\&+\sum_{i=1}^{n-1}C_i*C_{i+1}\\&+\sum_{i=1}^{n-2}C_i*C_{i+1}*C_{i+2}[(C_i,C_{i+2})is\ an\ edge\ in\ the\ graph]\end{al

poj 2288 Islands and Bridges

题意: 给你一个双向连通图,求 获得权值最大 的 哈密顿通路的 权值 和 这个权值对应的数目: 其中权值计算方法是  列如 ABCD  权值是a+b+c+d+ab+bc+cd 如果 A,B,C  和B,C,D 可构成三角形分别加上abc,bcd: 这个题 和poj 3311  很相像: 那个需要记录一个最后到达的地方   这个需要记录俩个罢了 DP[i][a][b]其中 i  二进制 中1表示这个点走过了   最后走的的 的是b>>a 因为对于已经走过了{1,2,3,4,,5,6,..,N}

POJ 2288 Islands and Bridges(状压dp)

Language: Default Islands and Bridges Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 9312   Accepted: 2424 Description Given a map of islands and bridges that connect these islands, a Hamilton path, as we all know, is a path along the b

poj 2288 Islands and Bridges ——状压DP

题目:http://poj.org/problem?id=2288 状压挺明显的: 一开始写了(记忆化)搜索,但一直T: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int const inf=0x3f3f3f3f; int T,n,m,v[15]; ll ans,cnt

【以前的空间】poj 2288 Islands and Bridges

一个不错的题解 : http://blog.csdn.net/accry/article/details/6607703 这是一道状态压缩.每个点有一个值,我们最后要求一个最值sum.sum由三部分组成:①每个点的值②每个点与他相邻的点的乘积③如果存在三个点成环,还要加上这三个点的值的乘积. 状态转移方程为:dp[i][j][k]=max(dp[i,j,k],dp[i'][k][l]+temp) j表示当前点,k表示上一个点,l表示上上一个点. 其中i,i'表示可以走到i点的状态,temp表示这

POJ 2288 Islands And Bridges 状态压缩dp+哈密顿回路

题意:n个点 m条边的图,路径价值定义为相邻点乘积,若路路径c[i-1]c[i]c[i+1]中c[i-1]-c[i+1]有边 则价值加上三点乘积找到价值最大的哈密顿回路,和相应的方法数n<=13.暴力dfs O(13!) TLE 由于n<13 经典的状态压缩dp [状态] [当前点位置 ][前一点位置] 注意上一个状态必须合法才能进行转移设状态dp[s][i][j] 当前状态为s,当前点为i上一个点为j的最大价值, ans=max(dp[(1<<n)-1][i])dp[s][i][

POJ 2288 Islands and Bridges(状压DP)题解

题意:n个点,m有向边,w[i]表示i的价值,求价值最大的哈密顿图(只经过所有点一次).价值为:所有点的w之和,加上,每条边的价值 = w[i] * w[j],加上,如果连续的三个点相互连接的价值 = w[i] * w[j] * w[k].n <= 13. 思路:dp[state][i][j]表示state状态下,最后两个为i,j. 代码: #include<cmath> #include<set> #include<map> #include<queue&

poj 2288 Islands and Bridges_状态压缩dp_哈密尔顿回路问题

题目链接 题目描写叙述:哈密尔顿路问题.n个点,每个点有权值,设哈密尔顿路为 C1C2...Cn,Ci的权值为Vi,一条哈密尔顿路的值分为三部分计算: 1.每个点的权值之和2.对于图中的每一条CiCi+1,加上Vi*Vi+1 3.对于路径中的连续三个点:CiCi+1Ci+2,若在图中,三点构成三角形,则要加上Vi*Vi+1*Vi+2 求一条汉密尔顿路能够获得的最大值,而且还要输出有多少条这种哈密尔顿路. 这道题的状态感觉不是非常难想,由于依据一般的哈密尔顿路问题,首先想到的是设计二维状态,dp[

POJ2288Islands and Bridges(状态压缩DP,求最大路和走条数)

Islands and Bridges Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 8845   Accepted: 2296 Description Given a map of islands and bridges that connect these islands, a Hamilton path, as we all know, is a path along the bridges such that i