ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2019-05-29 17:54:05  阅读:205  来源: 互联网

标签:2288 Bridges const int 题解 long maxn include 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
*/

 

标签:2288,Bridges,const,int,题解,long,maxn,include,dp
来源: https://www.cnblogs.com/KirinSB/p/10945242.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有