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[i , s]表示当前在i点,走过的点形成状态集合s。但是这道题在求解值的时候有一个不一样的地方,就是第三部分,如果还是设计成二维的状态,就会很麻烦,因为每加入一个新点,要判断新点、当前点、倒数第二个点是否构成三角形,所以要记录倒数第二个点。很自然地想到扩展状态的维数,增加一维,记录倒数第二个点。
1> 设计状态:
dp[i , j , s]表示当前站在j点,前一个点是i点,形成的状态集合是s,此时的最大值,way[i , j , s]记录当前状态下达到最大值的路径数;
2> 状态转移:
设k点不在集合s中,且存在边<j , k>
设q为下步到达k点获得的最大值
令r = s + (1<<k),为当前站在点k,前一个点为j,形成状态集合r
若i,j,k形成三角形,则q = dp[i][j][s] + v[k] + v[j]*v[k] + v[i]*v[j]*v[k]
否则,q = dp[i][j][s] + v[k] + v[j]*v[k];
若q大于dp[j][k][r];则:
dp[j][k][r] = q
way[j][k][r] = way[i][j][s];
若q等于dp[j][k][r],则:
way[j][k][r] += way[i][j][s];
3> 初始化:
显然,若i点到j点有边,则:
dp[i][j][(1<<i)+(1<<j)] = v[i] + v[j] + v[i]*v[j];
way[i][j][(1<<i)+(1<<j)] = 1;
4> 结果的产生:
最后的结果我们要枚举点i和j,找到最大的dp[i][j][(1<<n)-1],并且更新记录路径数ansp,最后ansp要除2才是结果,因为题目最后一句话,正向反向是一样的路。
此外,需要注意的是discuss提到的特殊情况,要用__int64,并且注意n等于1时,最大值就是第一个点的权值,路径数为1。
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN =13;
const int MAXS =1<<MAXN|1;
#define ll __int64
ll dp[MAXN][MAXN][MAXS],way[MAXN][MAXN][MAXS];
int map[MAXN][MAXN],v[MAXN];
int n,m,s;
void stateDp(){
int i,j,p,k;
memset(dp,-1,sizeof(dp));
memset(way,0,sizeof(way));
for(i=0;i<n;i++)
for(j=0;j<n;j++){
if(map[i][j]){
dp[i][j][(1<<i)+(1<<j)]=v[i]+v[j]+v[i]*v[j];
way[i][j][(1<<i)+(1<<j)]=1;
}
}
for(p=3;p<s;p++){
for(i=0;i<n;i++){
if(!(p&1<<i))//如果该状态第i城市没有路过就跳过
continue;
for(j=0;j<n;j++){
if(i==j||!(p&1<<j)||dp[i][j][p]==-1)
continue;
for(k=0;k<n;k++){
if(p&1<<k||!map[j][k])//如果k存在该状态则跳过
continue;
int r=p+(1<<k);//状态加入k城市
ll q=dp[i][j][p]+v[k]+v[j]*v[k];//更新价值
if(map[i][k]){//当构成环时更新价值
q+=v[i]*v[j]*v[k];
}
if(q>dp[j][k][r]){
dp[j][k][r]=q;
way[j][k][r]=way[i][j][p];
}else if(q==dp[j][k][r]){//相等时,有多个相等价值路径
way[j][k][r]+=way[i][j][p];
}
}
}
}
}
}
int main(int argc, char** argv) { int t,x,y,i,j;
scanf("%d",&t);
while(t--){
memset(map,0,sizeof(map));
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
scanf("%d",&v[i]);
for(i=0;i<m;i++){
scanf("%d%d",&x,&y);
map[x-1][y-1]=map[y-1][x-1]=1;
}
s=1<<n;
if(n==1){
printf("%d %d\n",v[0],1);
continue;
}
stateDp();
ll ansv=-1,ansp=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++){
if(i==j)continue;
if(dp[i][j][s-1]>ansv){//s-1为经过所有岛
ansv=dp[i][j][s-1];
ansp=way[i][j][s-1];
}else if(dp[i][j][s-1]==ansv){
ansp+=way[i][j][s-1];
}
}
printf("%I64d %I64d\n",ansv==-1?0:ansv,ansp/2);
}
return 0;
}
poj 2288 Islands and Bridges_状态压缩dp_哈密尔顿回路问题的更多相关文章
- poj 2288 Islands and Bridges——状压dp(哈密尔顿回路)
题目:http://poj.org/problem?id=2288 不知为什么记忆化搜索就是WA得不得了! #include<iostream> #include<cstdio> ...
- poj - 3254 - Corn Fields (状态压缩)
poj - 3254 - Corn Fields (状态压缩)超详细 参考了 @外出散步 的博客,在此基础上增加了说明 题意: 农夫有一块地,被划分为m行n列大小相等的格子,其中一些格子是可以放牧的( ...
- POJ 1691 Painting a Board(状态压缩DP)
Description The CE digital company has built an Automatic Painting Machine (APM) to paint a flat boa ...
- POJ 1632 Vase collection【状态压缩+搜索】
题目传送门:http://poj.org/problem?id=1632 Vase collection Time Limit: 1000MS Memory Limit: 10000K Total ...
- poj 3311 floyd+dfs或状态压缩dp 两种方法
Hie with the Pie Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6436 Accepted: 3470 ...
- poj 2411 Mondriaan's Dream_状态压缩dp
题意:给我们1*2的骨牌,问我们一个n*m的棋盘有多少种放满的方案. 思路: 状态压缩不懂看,http://blog.csdn.net/neng18/article/details/18425765 ...
- POJ 3254 Corn Fields(状态压缩)
一道状态压缩的题,错了好多次....应该先把满足的情况预处理出来 #include<iostream> #include<cstdio> #include<cstring ...
- POJ 2441 Arrange the Bulls 状态压缩递推简单题 (状态压缩DP)
推荐网址,下面是别人的解题报告: http://www.cnblogs.com/chasetheexcellence/archive/2012/04/16/poj2441.html 里面有状态压缩论文 ...
- POJ 1753 Flip Game (状态压缩 bfs+位运算)
Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 square ...
随机推荐
- (转)iOS7界面设计规范(1) - UI基础 - 为iOS7而设计
今天开个新坑.其实老早就想做这事儿了.记得前一两年,苹果官方还会在开发者中心提供中文的HIG(Human Interface Guideline),后来给没了:网上能够找到的中文版本不知是官方还是同行 ...
- 泛型 Field 和 SetField 方法 (LINQ to DataSet)
LINQ to DataSet 为 DataRow 类提供用于访问列值的扩展方法:Field 方法和 SetField 方法.这些方法使开发人员能够更轻松地访问列值,特别是 null 值.DataSe ...
- Java八个并发学习——线程同步工具CyclicBarrier
本文是一篇文章对网络的研究摘要,感谢您的无私分享. CyclicBarrier 类有一个整数初始值,此值表示将在同一点同步的线程数量.当当中一个线程到达确定点,它会调用await() 方法来等待其它线 ...
- 有关android 应用的plugin框架调研
1. 借助android提供的shareduserid属性使多个不同的apt共用一个userid,以扫除权限壁垒,获取插件context,继而获取view并加载插件.这种方式是建立在已经安装完成的ap ...
- C# winform带进度条的图片下载
代码如下: public partial class FrmMain : Form { public FrmMain() { InitializeComponent(); } private void ...
- RHEL-resolv.conf文件修改后重启被还原
修改resolve.conf文件之后,reboot或service restart network时,修改的内容被还原.关闭NetworkManager即可.# chkconfig |grep Net ...
- 【转】Xcode升到6.4插件失效,与添加插件不小心点击Skip Bundle解决办法
转载自:http://www.jianshu.com/p/d51547d29309 今天升级了xcode到6.4 发现之前装的插件不能使用了.这里有一个解决的方案: 步骤如下: 一.查看Xcode的U ...
- Javascript进阶篇——(DOM—节点---获取浏览器窗口可视区域大小+获取网页尺寸)—笔记整理
浏览器窗口可视区域大小获得浏览器窗口的尺寸(浏览器的视口,不包括工具栏和滚动条)的方法:一.对于IE9+.Chrome.Firefox.Opera 以及 Safari: • window.innerH ...
- 《第一行代码》学习笔记10-活动Activity(8)
1.除了onRestart()方法,其他都是两两相对的.三种生存期: (1)完整生存期:onCreate()~onDestroy().一般情况下,一个活动会在onCreate()中完成各种初始化操作, ...
- hive函数总结-日期函数
获取当前UNIX时间戳函数: unix_timestamp语法: unix_timestamp() 返回值: bigint说明: 获得当前时区的UNIX时间戳举例: hive> select u ...