题目链接:http://poj.org/problem?id=2288

题目:

题意:求Hamilton 路径权值的最大值,且求出有多少条权值这么大的Hamilton路径。

思路:状压dp,dp[i][j][k]表示第i种状态下倒数第二个岛屿为j倒数第一个岛屿为k下的权值,cnt[i][j][k]记录条数。

  当有边(i,j)存在时,有如下初值可赋:
  d[(1<<i)+(1<<j)][i][j]=val[i]+val[j]+val[i]*val[j],cnt[(1<<i)+(1<<j)][i][j]=1。
  
如果状态(state,i,j)可达,检查岛k,如果此时k没有被访问过并且有边(j,k)存在,则做如下操作:
  1)设tmp为下一步访问岛k时获得的总利益,r=state+(1<<k)。
  2)如果tmp>d[r][j][k],表示此时可以更新到更优解,则更新:
      d[r][j][k]=tmp,cnt[r][j][k]=cnt[state][i][j]。
  3)如果tmp==d[r][j][k],表示此时可以获得达到局部最优解的更多方式,则更新:
      cnt[r][j][k]+=cnt[state][i][j]。
  最后检查所有的状态((1<<n)-1,i,j),叠加可以得到最优解的道路数。
  需要注意的是,题目约定一条路径的两种行走方式算作一种,所以最终结果要除2。

代码实现如下:

 #include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;;
typedef pair<int, int> pii;
typedef unsigned long long ull; #define lson i<<1
#define rson i<<1|1
#define bug printf("*********\n");
#define FIN freopen("D://code//in.txt", "r", stdin);
#define debug(x) cout<<"["<<x<<"]" <<endl;
#define IO ios::sync_with_stdio(false),cin.tie(0); const double eps = 1e-;
const int mod = ;
const int maxn = (<<) + ;
const double pi = acos(-);
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f; int t, n, m, u, v;
int w[], mp[][];
ll dp[maxn][][], cnt[maxn][][]; int main() {
//FIN;
scanf("%d", &t);
while(t--) {
memset(mp, , sizeof(mp));
memset(dp, -, sizeof(dp));
memset(cnt, , sizeof(cnt));
scanf("%d%d", &n, &m);
for(int i = ; i <= n; ++i) {
scanf("%d", &w[i]);
}
for(int i = ; i <= m; ++i) {
scanf("%d%d", &u, &v);
mp[u][v] = mp[v][u] = ;
}
if(n == ) {
printf("%d 1\n", w[]);
continue;
}
for(int i = ; i <= n; ++i) {
for(int j = ; j <= n; ++j) {
if(i != j && mp[i][j]) {
dp[(<<(i-))|(<<(j-))][i][j] = w[i] + w[j] + (ll) w[i] * w[j];
cnt[(<<(i-))|(<<(j-))][i][j] = ;
}
}
}
int tot = << n;
for(int i = ; i < tot; ++i) {
for(int j = ; j <= n; ++j) {
if(i & (<<(j-))) {
for(int k = ; k <= n; ++k) {
if(j != k && (i & (<<(k-))) && mp[j][k] && dp[i][j][k] != -) {
for(int x = ; x <= n; ++x) {
if(j != x && k != x && mp[k][x] && (i & (<<(x-))) == ) {
ll tmp = dp[i][j][k] + w[x] + (ll)w[k] * w[x];
if(mp[j][x]) tmp += (ll)w[k] * w[j] * w[x];
if(tmp > dp[i|(<<(x-))][k][x]) {
dp[i|(<<(x-))][k][x] = tmp;
cnt[i|(<<(x-))][k][x] = cnt[i][j][k];
} else if(tmp == dp[i|(<<(x-))][k][x]){
cnt[i|(<<(x-))][k][x] += cnt[i][j][k];
}
}
}
}
}
}
}
}
ll ans1 = , ans2 = ;
for(int i = ; i <= n; ++i) {
for(int j = ; j <= n; ++j) {
if(i == j) continue;
if(dp[tot-][i][j] > ans1) {
ans1 = dp[tot-][i][j];
ans2 = cnt[tot-][i][j];
} else if(dp[tot-][i][j] == ans1) {
ans2 += cnt[tot-][i][j];
}
}
}
printf("%lld %lld\n", ans1, ans2 / );
}
return ;
}

Islands and Bridges(POJ2288+状压dp+Hamilton 回路)的更多相关文章

  1. POJ 2288 Islands and Bridges (状压DP,变形)

    题意: 给一个无向图,n个点m条边,每个点有点权,要求找到一条哈密顿路径,使得该路径的f(path)值最大.输出f值,若有多条最大f值的路径,输出路径数量. f值由如下3点累加而来: (1)所有点权之 ...

  2. poj 2288 Islands and Bridges (状压dp+Tsp问题)

    这道题千辛万苦啊! 这道题要涉及到当前点和前面两个点,那就设dp[state][i][j]为当前状态为state,当前点为i,前一个点为j 这个状态表示和之前做炮兵那题很像,就是涉及到三个点时,就多设 ...

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

    题意:n个点,m有向边,w[i]表示i的价值,求价值最大的哈密顿图(只经过所有点一次).价值为:所有点的w之和,加上,每条边的价值 = w[i] * w[j],加上,如果连续的三个点相互连接的价值 = ...

  4. POJ 2288 Islands and Bridges(状压dp)

    http://poj.org/problem?id=2288 题意: 有n个岛屿,每个岛屿有一个权值V,一条哈密顿路径C1,C2,...Cn的值为3部分之和: 第1部分,将路径中每个岛屿的权值累加起来 ...

  5. CH0103最短Hamilton路径 & poj2288 Islands and Brigdes【状压DP】

    虐狗宝典学习笔记: 取出整数\(n\)在二进制表示下的第\(k\)位                                                    \((n >> ...

  6. 最短Hamilton路径(状压dp)

    最短Hamilton路径实际上就是状压dp,而且这是一道作为一个初学状压dp的我应该必做的题目 题目描述 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 ...

  7. AcWing 最短Hamilton距离 (状压DP)

    题目描述 给定一张 n 个点的带权无向图,点从 0∼n−1 标号,求起点 0 到终点 n−1 的最短 Hamilton 路径. Hamilton 路径的定义是从 0 到 n−1 不重不漏地经过每个点恰 ...

  8. 状压DP天秀

    状压DP,依靠的是把状态用某种压缩方式表示出来进而DP,大多数时候是二进制状压. 直接看例题吧. 一双木棋     九尾狐吃棉花糖     islands and bridges 愤怒的小鸟   芯片 ...

  9. CF11D A Simple Task(状压DP)

    \(solution:\) 思路大家应该都懂: 状压DP:\(f[i][j]\),其中 \(i\) 这一维是需要状压的,用来记录19个节点每一个是否已经走过(走过为 \(1\) ,没走为 \(0\) ...

随机推荐

  1. 蜗牛慢慢爬 LeetCode 1.Two Sum [Difficulty: Easy]

    题目 Given an array of integers, return indices of the two numbers such that they add up to a specific ...

  2. PDO笔记

    <?php/* * 查询操作主要是PDO::query().PDO::exec().PDO::prepare().PDO::query()主要是用于有记录结果返回的操作,特别是SELECT操作, ...

  3. javascript与python的比较

    1:javascript与python大小写皆敏感 2:javascript使用{}来组织代码块,与大部分语言相同  python使用缩进来组织代码块,与大部分语言不同,请务必遵守约定俗成的习惯,坚持 ...

  4. 怎么用JavaScript实现tab切换

    先看一下代码实现后的最终效果: 用JavaScript实现思路很简单,就是先把所有的内容隐藏,点击标题对应的内容显示, css代码如下: <style type="text/css&q ...

  5. 第132天:移动web端-rem布局(进阶)

    rem布局(进阶版) 该方案使用相当简单,把下面这段已压缩过的 原生JS(仅1kb,源码已在文章底部更新,2017/5/3) 放到 HTML 的 head 标签中即可(注:不要手动设置viewport ...

  6. Web模块:spring-boot-starter-web

    spring-boot-autoconfigure-1.5.1.RELEASE.jar!/org/springframework/boot/autoconfigure/web 上述jar的web包下, ...

  7. request之setAtrribute

    当在servlet中有request.SetAtrribute("AtriruteName",AtrributeValue)语句时,在jsp页面获取AtrributeValue有两 ...

  8. P3916 图的遍历

    题目描述 给出 NNN 个点, MMM 条边的有向图,对于每个点 vvv ,求 A(v)A(v)A(v) 表示从点 vvv 出发,能到达的编号最大的点. 输入输出格式 输入格式: 第1 行,2 个整数 ...

  9. TCP的拥塞控制 (三)

    1.   Multiple Packet Losses Fast Retransmit/Fast Recovery机制可以很好地处理单个packet丢失的问题,但当大量packet同时丢包时(一个RT ...

  10. BZOJ3262:陌上花开 & 洛谷3810:三维偏序——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3262 https://www.luogu.org/problemnew/show/3810 Desc ...