Islands and Bridges(POJ2288+状压dp+Hamilton 回路)
题目链接: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 回路)的更多相关文章
- POJ 2288 Islands and Bridges (状压DP,变形)
题意: 给一个无向图,n个点m条边,每个点有点权,要求找到一条哈密顿路径,使得该路径的f(path)值最大.输出f值,若有多条最大f值的路径,输出路径数量. f值由如下3点累加而来: (1)所有点权之 ...
- poj 2288 Islands and Bridges (状压dp+Tsp问题)
这道题千辛万苦啊! 这道题要涉及到当前点和前面两个点,那就设dp[state][i][j]为当前状态为state,当前点为i,前一个点为j 这个状态表示和之前做炮兵那题很像,就是涉及到三个点时,就多设 ...
- POJ 2288 Islands and Bridges(状压DP)题解
题意:n个点,m有向边,w[i]表示i的价值,求价值最大的哈密顿图(只经过所有点一次).价值为:所有点的w之和,加上,每条边的价值 = w[i] * w[j],加上,如果连续的三个点相互连接的价值 = ...
- POJ 2288 Islands and Bridges(状压dp)
http://poj.org/problem?id=2288 题意: 有n个岛屿,每个岛屿有一个权值V,一条哈密顿路径C1,C2,...Cn的值为3部分之和: 第1部分,将路径中每个岛屿的权值累加起来 ...
- CH0103最短Hamilton路径 & poj2288 Islands and Brigdes【状压DP】
虐狗宝典学习笔记: 取出整数\(n\)在二进制表示下的第\(k\)位 \((n >> ...
- 最短Hamilton路径(状压dp)
最短Hamilton路径实际上就是状压dp,而且这是一道作为一个初学状压dp的我应该必做的题目 题目描述 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 ...
- AcWing 最短Hamilton距离 (状压DP)
题目描述 给定一张 n 个点的带权无向图,点从 0∼n−1 标号,求起点 0 到终点 n−1 的最短 Hamilton 路径. Hamilton 路径的定义是从 0 到 n−1 不重不漏地经过每个点恰 ...
- 状压DP天秀
状压DP,依靠的是把状态用某种压缩方式表示出来进而DP,大多数时候是二进制状压. 直接看例题吧. 一双木棋 九尾狐吃棉花糖 islands and bridges 愤怒的小鸟 芯片 ...
- CF11D A Simple Task(状压DP)
\(solution:\) 思路大家应该都懂: 状压DP:\(f[i][j]\),其中 \(i\) 这一维是需要状压的,用来记录19个节点每一个是否已经走过(走过为 \(1\) ,没走为 \(0\) ...
随机推荐
- c文法
程序→<外部声明>|<程序> 外部声明→<功能定义>|<声明> 功能定义→<声明复合语句的类型> 类型→<VOID| CHAR| IN ...
- C#控件之Repeater控件使用
歡迎大家來討論,修改,一定虛心接受. 1.為什麼使用Repeater控件? 關於把從數據庫讀取的數據綁定到前台頁面,我們可以使用DataGrid.DataGridView以及Repeater來佈局,三 ...
- 2nd 历年学生作品评论(3部)
历年学生作品评论(3部) 1.基于GUI的图书管理系统 利用NABCD模型进行竞争性需求分析:http://www.cnblogs.com/chitty/p/4546876.html 测试说明书: h ...
- 结对编程——paperOne基于java web的简易四则运算出题网站
项目成员:张金生 张政 需求分析: 1.要进行四则运算: 2.运算题目随机: 3.进行对错判断: 4.整数运算. 程序概要: 1.用JSP实现: 2.用户可选择题目数量: 3.答题页用表格列出 ...
- Jmeter 快速入门--初识线程组
添加线程组 (1)thread group(线程组),setup thread group相当于lr初始化“环境”的初始化脚本,teardown thread group相当于lr测试完毕后对应的清除 ...
- 第96天:CSS3 背景详解
一.背景大小 background: url("images/bg.jpg") no-repeat;控制背景的大小1.具体数值background-size: 500px 500p ...
- HDU3507_Print Article
这个题目又是一个典型的dp斜率优化的题目.题意是给你n个数,你需要做的是把这个n个数分为连续的若干段,每段的权值为这段数字的和的平方加上M.求最小的总权值. 我们可以根据题意写出朴素版的dp状态转移方 ...
- [Code Festival 2017 qual A] B: flip
题意 给出一个n行m列初始全白的矩阵,每次可以翻转一行/一列的全部格子的颜色.问任意次操作后能否使得恰好有k个黑色格子. n,m<=1000 分析 显然要么翻转一次要么不翻转. 最终黑色格子数只 ...
- 测试开发面试的Linux面试题总结之二:常用命令
(1)Linux的文件系统目录配置要遵循FHS规范,规范定义的两级目录规范如下: /home 每个账号在该目录下都有一个文件夹,进行数据的管理 /usr 有点像windo ...
- static_cast 和 dynamic_cast
1.static_cast static_cast < type-id > ( expression ) 该运算符把expression转换为type-id类型,但没有运行时类型检查来保证 ...