【Islands and Bridges】题解
题目
题目描述
给定一些岛屿和一些连接岛屿的桥梁,大家都知道汉密尔顿路是访问每个岛屿一次的路线,在我们这个地图中,每个岛屿有个正整数的权值,表示这个岛屿的观赏价值。假设一共有N个岛屿,用Vi表示岛屿Ci的价值,汉密尔顿路C1C2....Cn的价值是以下三部分的总和:
  (1)所有岛屿的价值之和;
  (2)对于路径中相邻的两个岛屿CiCi+1,把两个岛屿的价值之积加到总价值中;
  (3)路径中连续三个岛屿CiCi+1Ci+2,如果Ci与Ci+2有桥直接相连,则把这三个岛屿价值之积加到总价值中。
  要求计算汉密尔顿路最大的价值以及方案数。
输入
输入第一行是一个整数Q(Q<=20),表示测试数据的数量。每个测试数据第一行输入两个整数N和M,分别表示岛屿数和桥梁数,接下来一行包含N个正整数,第i个数表示Vi,每个数不超过100,最后M行,每行两个数X,Y,表示岛X和岛Y之间有一座桥直接相连,桥是双向的,岛屿编号为1到N(N<=13)
输出
对于每个测试数据,输出一行,两个整数,第一个数表示最大价值,第二个数表示方案数,如果不存在汉密尔顿路径,输出“0 0”
注意:一条路径可以反着走,我们认为这两条路径是同一条路径。
样例输入
2
3 3
2 2 2
1 2
2 3
3 1
4 6
1 2 3 4
1 2
1 3
1 4
2 3
2 4
3 4
样例输出
22 3
69 1
分析
对于第一问,因为N<=13,所以我们可以用状态压缩dp,压缩每个点是否走过的状态;当路径中连续三个岛屿CiCi+1Ci+2,Ci与Ci+2有桥直接相连时,就需要知道Ci和Ci+1这两个点。所以dp方程为f[i][j][k],指在状态i的时候,走到了k点,上一个走到的点是j的最大值。dp方程转移为:
f[i+bb[l]][k][l]=max(f[i+bb[l]][k][l],f[i][j][k]+v[k]v[l]+v[l]) **//bb数组存2^i
**f[i+bb[l]][k][l]=max(f[i+bb[l]][k][l],f[i][j][k]+v[k]v[l]+v[j]v[k]v[l]+v[l])//j和l有路径相通
对于第二问,因为要求最大的价值的方案数,所以用g[i][j][k]指在状态i的时候,走到了k点,上一个走到的点是j的最大值的方案数。如果可以转移时但不相等就覆盖答案,只有在可以转移时并且相等才能累加答案。最后统计当价值为最大时的方案数。
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
long long g[10001][20][20],f[10001][20][20];
long long n,m,e,v[30];
long long bb[30];
bool b[30][30];
int main()
{
	cin>>e;
	long long x,y;
	bb[1]=1;
	int i,j,k,l;
	for(i=2;i<=29;i++)
	  	bb[i]=bb[i-1]*2;
	while(e--)
	{
		scanf("%lld%lld",&n,&m);
		for(i=0;i<=10000;i++)
		    for(j=0;j<=19;j++)
		        for(k=0;k<=19;k++)
		        {
		    		f[i][j][k]=0;
		    		g[i][j][k]=0;
				}
		for(i=0;i<=n;i++)
		    for(j=0;j<=n;j++)
		    {
		        b[i][j]=false;
			}
		for(i=1;i<=n;i++)
		{
			scanf("%lld",&v[i]);
		}
		for(i=1;i<=m;i++)
		{
			scanf("%lld%lld",&x,&y);
			b[x][y]=b[y][x]=true;
			f[bb[x]+bb[y]][x][y]=f[bb[x]+bb[y]][y][x]=v[x]*v[y]+v[x]+v[y];//初始化f数组
			g[bb[x]+bb[y]][x][y]=g[bb[x]+bb[y]][y][x]=1;//初始化g数组
		}
		for(i=0;i<=bb[n+1]-1;i++)
		{
			for(j=1;j<=n;j++)
				if((bb[j] | i)==i)
					for(k=1;k<=n;k++)
			  			if((bb[k] | i)==i && b[j][k]){if(!g[i][j][k]) continue;
			  				for(l=1;l<=n;l++)
			  			    	if((bb[l] | i)!=i && b[k][l] && b[j][l])//当j和l有路径相同
			  			    	{
			  			        	if(f[i+bb[l]][k][l]==f[i][j][k]+v[k]*v[l]+v[j]*v[k]*v[l]+v[l])
			  			        		g[i+bb[l]][k][l]+=g[i][j][k];
									else
									//当j和l无路径相同
									if(f[i+bb[l]][k][l]<f[i][j][k]+v[k]*v[l]+v[j]*v[k]*v[l]+v[l])
									{
										f[i+bb[l]][k][l]=f[i][j][k]+v[k]*v[l]+v[j]*v[k]*v[l]+v[l];
			  			        		g[i+bb[l]][k][l]=g[i][j][k];
									}
								}
								else
			  			    	if((bb[l] | i)!=i && b[k][l])
			  			    	{
			  			        	if(f[i+bb[l]][k][l]==f[i][j][k]+v[k]*v[l]+v[l])
			  			        		g[i+bb[l]][k][l]+=g[i][j][k];
									else
									if(f[i+bb[l]][k][l]<f[i][j][k]+v[k]*v[l]+v[l])
									{
			  			            	f[i+bb[l]][k][l]=f[i][j][k]+v[k]*v[l]+v[l];
			  			        		g[i+bb[l]][k][l]=g[i][j][k];
									}
								}}
		}
		long long ans=0;
		long long ma=0;
		for(i=1;i<=n;i++)
		    for(j=1;j<=n;j++)
		    {
		    	if(f[bb[n+1]-1][i][j]>ma)
		    	{
		    		ma=f[bb[n+1]-1][i][j];
		    		ans=g[bb[n+1]-1][i][j];
				}
				else
				if(f[bb[n+1]-1][i][j]==ma)
				{
					ans+=g[bb[n+1]-1][i][j];
				}
			}
		if(n==1) cout<<v[1]<<' '<<1<<endl;else
		if(ma==0 || ans==0) cout<<0<<' '<<0<<endl;else
		printf("%lld %lld\n",ma,ans/2);
	}
}
【Islands and Bridges】题解的更多相关文章
- POJ2288 Islands and Bridges
		Description Given a map of islands and bridges that connect these islands, a Hamilton path, as we al ... 
- 【状压dp】Islands and Bridges
		Islands and Bridges Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 11034 Accepted: 2 ... 
- [poj2288] Islands and Bridges (状压dp)
		Description Given a map of islands and bridges that connect these islands, a Hamilton path, as we al ... 
- HDU 1668 Islands and Bridges
		Islands and Bridges Time Limit: 4000ms Memory Limit: 65536KB This problem will be judged on HDU. Ori ... 
- POJ 2288 Islands and Bridges(状压DP)题解
		题意:n个点,m有向边,w[i]表示i的价值,求价值最大的哈密顿图(只经过所有点一次).价值为:所有点的w之和,加上,每条边的价值 = w[i] * w[j],加上,如果连续的三个点相互连接的价值 = ... 
- 【以前的空间】poj 2288 Islands and Bridges
		一个不错的题解 : http://blog.csdn.net/accry/article/details/6607703 这是一道状态压缩.每个点有一个值,我们最后要求一个最值sum.sum由三部分组 ... 
- poj 2288 Islands and Bridges (状压dp+Tsp问题)
		这道题千辛万苦啊! 这道题要涉及到当前点和前面两个点,那就设dp[state][i][j]为当前状态为state,当前点为i,前一个点为j 这个状态表示和之前做炮兵那题很像,就是涉及到三个点时,就多设 ... 
- DP:Islands and Bridges(POJ 2288)
		2015-09-21 造桥基建工程 题目大意,就是有n座岛和k座桥,要你找一条哈密顿圈(找完所有的岛,并且每个岛只经过一次),当经过一座岛就加上岛的价值,如果两岛联通,则加上两座岛的价值之积,如果三座 ... 
- POJ2288 Islands and Bridges(TSP:状压DP)
		求一个图的哈密顿路径的最大权及其路径数.显然状态压缩+DP. dp[v][u][S] 表示从v走到当前顶点 u且走过的顶点集合是S的 最大权值和方案数 这题我用记忆化搜索,从终点开始递归进行,感觉这样 ... 
随机推荐
- JForum论坛安装以及部署(转)
			链接地址:https://www.cnblogs.com/Amos-Turing/p/7151009.html 下载JForum2.1.9 包手动放到tomcat的webapps下面, 这次打开网址: ... 
- java:Oracle(视图,索引,序列)
			1.索引:索引一共分为4种 -- 在oracle中, -- normal:普通索引 -- unique:唯一索引 -- bitmap:位图索引 -- B 树索引:默认:如果不建立索引的情况下,orac ... 
- opencv2中访问像素的简单方法-自定义一个宏CV_MAT_ELEM2
			利用Mat的step[0],step[1]访问像素的行列,自定义一个宏CV_MAT_ELEM2(src,dtype,y,x),src是待访问的Mat,dtype是src的数据类型(int,float, ... 
- python学习之那些由print引起的困惑
			该文索所起之因:在练习列表的操作时,要输出一波操作后的列表,但是一直让本人耿耿于怀的时下边的这个现象: 红色框框里是字符串,黄色框框里是列表,同样是只对一个元素进行的操作,为啥输出时字符串是作为一个整 ... 
- Java内存溢出
			中间件应用Java内存溢出常见的三种情况: 1.OutOfMemoryError: Java heap space 2.OutOfMemoryError: PermGen space 3.OutOfM ... 
- FPGA —— LED控制
			第一次接触新东西的时候,难免会磕磕碰碰,不过遇到问题不要着急,慢慢来.原因总归是我们自己引起的,一步步找到问题的根源,然后彻底解决它,避免下次再犯. 在开始之前先分享一下工具:(Quartus II ... 
- HDU 1133 Buy the Ticket (数学、大数阶乘)
			Buy the Ticket Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ... 
- Linux系统装mycat
			最近在Linux系统中装载了一下mycut,记录过程以及所遇到的异常 首先是mycut的压缩包,直接放到linux中解压即可 链接:https://pan.baidu.com/s/1qo7z4tNvk ... 
- springboot笔记-文件上传
			使用 Spring Boot 和 Thymeleaf 上传文件 Spring Boot 利用 MultipartFile 的特性来接收和处理上传的文件,本示例前端页面使用 Thymeleaf 来处理. ... 
- php中文网--JavaScript
			PHP中文网:http://www.php.cn/course/18.html 常用的两个客户端输出方法 document.write("你好呀js"); 描述:在网页的<b ... 
