题目

题目描述

给定一些岛屿和一些连接岛屿的桥梁,大家都知道汉密尔顿路是访问每个岛屿一次的路线,在我们这个地图中,每个岛屿有个正整数的权值,表示这个岛屿的观赏价值。假设一共有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】题解的更多相关文章

  1. POJ2288 Islands and Bridges

    Description Given a map of islands and bridges that connect these islands, a Hamilton path, as we al ...

  2. 【状压dp】Islands and Bridges

    Islands and Bridges Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 11034   Accepted: 2 ...

  3. [poj2288] Islands and Bridges (状压dp)

    Description Given a map of islands and bridges that connect these islands, a Hamilton path, as we al ...

  4. HDU 1668 Islands and Bridges

    Islands and Bridges Time Limit: 4000ms Memory Limit: 65536KB This problem will be judged on HDU. Ori ...

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

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

  6. 【以前的空间】poj 2288 Islands and Bridges

    一个不错的题解 : http://blog.csdn.net/accry/article/details/6607703 这是一道状态压缩.每个点有一个值,我们最后要求一个最值sum.sum由三部分组 ...

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

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

  8. DP:Islands and Bridges(POJ 2288)

    2015-09-21 造桥基建工程 题目大意,就是有n座岛和k座桥,要你找一条哈密顿圈(找完所有的岛,并且每个岛只经过一次),当经过一座岛就加上岛的价值,如果两岛联通,则加上两座岛的价值之积,如果三座 ...

  9. POJ2288 Islands and Bridges(TSP:状压DP)

    求一个图的哈密顿路径的最大权及其路径数.显然状态压缩+DP. dp[v][u][S] 表示从v走到当前顶点 u且走过的顶点集合是S的 最大权值和方案数 这题我用记忆化搜索,从终点开始递归进行,感觉这样 ...

随机推荐

  1. angularjs的部分总结

    就在这个星期,我们学习了一个神奇的框架叫:"Angular js",它的神奇之处不是它的功能有多强,甚至它的功能还是很简陋的,但是它的那种思想是非常牛逼的;他完全抛弃了我们现在所常 ...

  2. java.sql.SQLSyntaxErrorException: ORA-00923: 未找到要求的 FROM 关键字

    ssm(Oracle)配置druid数据库连接池,正常启动项目,但是请求访问数据库时报错 “java.sql.SQLSyntaxErrorException: ORA-00923: 未找到要求的 FR ...

  3. 逻辑回归2-scikit-learn参数介绍

    1.1     scikit-learn参数介绍 1.1.1  导入 from sklearn.linear_model import LogisticRegression 1.1.2  版本 sci ...

  4. ios模拟器快捷键

    shift+cmd+h  返回桌面 cmd+5或者4或者3  可以直接调节大小 cmd+R运行项目 cmd+R弹出键盘 ios模拟器弹出键盘 在xcode6中, 模拟器中的键盘和电脑的键盘可以进行绑定 ...

  5. linxu passwd 给linux用户设置密码 命令

    [root@localhost ~]# passwd # 修改 root 用户的密码 passwd 给linux用户设置密码 命令 passwd www 直接passwd是当前用户设置密码 非交互式修 ...

  6. Redis配置主从时报错“Could not connect to Redis at 192.168.0.50:6379: Connection refused not connected>”

    配置Redis主从时,修改完从节点配置文件,然后报错 [root@Rich七哥-0-50 redis]# /opt/redis/redis-cli -h 192.168.0.50 Could not ...

  7. [转帖]VMWare官网:无法关闭 ESXi 主机上的虚拟机 (1014165)

    无法关闭 ESXi 主机上的虚拟机 (1014165) https://kb.vmware.com/s/article/1014165?lang=zh_CN Last Updated: 4/17/20 ...

  8. Codeforces 1209F. Koala and Notebook

    传送门 考虑到达某个点时的数长度要尽量短,那么可以把边长看成此边十进制下的位数 那么对于最终答案我们只要考虑最短路 $DAG$ 上的情况 又发现其实边长都很小,所以可以暴力拆边,把边权都拆成 $1$, ...

  9. EasyTest-接口自动化测试平台部署上线问题记录

    平台url:   http://easytest.xyz 花巨资搞了个阿里云服务器,哈哈,有想体验指导的大佬私聊我~~~ 部署环境 云服务器:Ubuntu Server 16.04.1 LTS 64位 ...

  10. eclipse中web项目tomcat的设置

    1.  出现的问题: web开发中(eclipse环境),为本地项目添加tomcat,我们一般都会选择直接添加.在本次开发中突然遇到一个问题:因为项目涉及到文件上传,我利用MultipartFile进 ...