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

Posted kirinsb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-8;
const int maxn = 15 + 10;
const int M = maxn * 30;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1e4 + 7;
int w[maxn];
int n, m;
int g[maxn][maxn];
int dp[(1 << 13) + 10][maxn][maxn];
ll way[(1 << 13) + 10][maxn][maxn];
void solve(){
    memset(dp, -1, sizeof(dp));
    memset(way, 0, sizeof(way));
    for(int i = 0; i < n; i++){
        for(int j = 0; j < n; j++){
            if(i == j) continue;
            if(g[i][j] == INF) continue;
            dp[(1 << i) | (1 << j)][i][j] = w[i] + w[j] + g[i][j];
            way[(1 << i) | (1 << j)][i][j]++;
        }
    }
    for(int t = 0; t < (1 << n) - 1; t++){
        for(int i = 0; i < n; i++){
            if(!((1 << i) & t)) continue;
            for(int j = 0; j < n; j++){
                if(!((1 << j) & t)) continue;
                if(g[i][j] == INF) continue;
                if(dp[t][i][j] == -1) continue;
                for(int k = 0; k < n; k++){
                    if((1 << k) & t) continue;
                    if(g[j][k] == INF) continue;
                    ll ret = dp[t][i][j] + w[k] + g[j][k];
                    if(g[i][k] != INF) ret += w[i] * w[j] * w[k];
                    if(dp[(1 << k) | t][j][k] < ret){
                        dp[(1 << k) | t][j][k] = ret;
                        way[(1 << k) | t][j][k] = way[t][i][j];
                    }
                    else if(dp[(1 << k) | t][j][k] == ret){
                        way[(1 << k) | t][j][k] += way[t][i][j];
                    }
                }
            }
        }
    }
}
int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++)
            scanf("%d", &w[i]);
        memset(g, INF, sizeof(g));
        for(int i = 0; i < m; i++){
            int u, v;
            scanf("%d%d", &u, &v);
            u--, v--;
            g[u][v] = g[v][u] = w[u] * w[v];
        }
        if(n == 1){
            printf("%d 1\n", w[0]);
            continue;
        }
        solve();
        ll ans = 0, num = 0;
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                if(i == j) continue;
                if(g[i][j] == INF) continue;
                if(dp[(1 << n) - 1][i][j] > ans){
                    ans = dp[(1 << n) - 1][i][j];
                    num = way[(1 << n) - 1][i][j];
                }
                else if(dp[(1 << n) - 1][i][j] == ans){
                    num += way[(1 << n) - 1][i][j];
                }
            }
        }
        printf("%lld %lld\n", ans, num / 2);
    }
    return 0;
}
/*
3
3 1
2 2 2
1 2
*/

 

以上是关于POJ 2288 Islands and Bridges(状压DP)题解的主要内容,如果未能解决你的问题,请参考以下文章

POJ2288 Islands and Bridges (DP)

poj 2288 Islands and Bridges ——状压DP

POJ 2288 Islands and Bridges(状压dp)

以前的空间poj 2288 Islands and Bridges

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

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