DP:Islands and Bridges(POJ 2288)
2015-09-21

题目大意,就是有n座岛和k座桥,要你找一条哈密顿圈(找完所有的岛,并且每个岛只经过一次),当经过一座岛就加上岛的价值,如果两岛联通,则加上两座岛的价值之积,如果三座岛之间构成三角联通,则再加上三岛之积,问最大价值的哈密顿圈和最大价值和哈密顿圈的个数
哈密顿圈是是一个NP完全的问题,用DP就可以解决这个问题,现在的问题就是,怎么解决呢?
首先我们要明确,这一题要用DP做什么,首先这一题的最后肯定要求到最后岛全部都通过的情况,然后还需要保留前两个岛的信息
那么这个时候我们可以想到用状态压缩去做(因为这里岛只能经过一次,而且经过以后状态都是等效的)101111,就表示第五个岛还没被经过,本来呢这个状态压缩应该是保留状态的,但是这样一来我们就需要保留1<<n个*3个维度,那么这一题我们可以放弃了,因为内存肯定不够,所以我们要想着优化储存空间,由于我们只用担心前两个岛是什么,而不是岛的所在状态(反正表示也是1001111)这样的,所以我们可以把两个岛的维度改为n*n,那么最后dp就是一个[1<<n][n][n]的三维数组
具体而言,对于不合法的位置,我们老方法,要定义其为-1,同时还要判断图是否联通
我们先从i=1(0000....0001)开始枚举,表示岛已经经过的位置,如果我们需要上一次还没来到这个岛的位置的状态,我们使用i^(1<<(j-1))这个方法,并且判断第j个岛的前两座岛是否有冲突。
如果算出来的dp值比dp[i][j][k]要大,则更新,并且num是继承dp[state_old][k][q]的状态,如果想等,则使num[i][j][k]+=num[state_old][k][q](表示还有更多的路与此状态相关)。
最后基准状态,q=0的时候可以放入岛的价值,那么最后就可以一起处理了,并且只有一个岛的时候,要单独处理,并且数据类型要是long long
参考:http://blog.csdn.net/lenleaves/article/details/7981788
#include <stdio.h>
#include <stdlib.h>
#include <string.h> static int islands_value[];
int map[][];
long long dp[ << ][][];//因为要保存两个以上状态,所以必须是三维数组,前面一位是状态数
long long num[ << ][][]; void Search(const int);
static int If_Valid(const int, const int); int main(void)
{
int sum_islands, sum_paths, sum_obj, i, j, k, x, y; scanf("%d", &sum_obj);
for (i = ; i < sum_obj; i++)//输入
{
scanf("%d%d", &sum_islands, &sum_paths);
for (j = ; j <= sum_islands; j++)
scanf("%d", &islands_value[j]);
memset(map, , sizeof(map));
memset(dp, -, sizeof(dp));
memset(num, , sizeof(num));
for (k = ; k < sum_paths; k++)
{
scanf("%d%d", &x, &y);
map[x][y] = map[y][x] = ;//读图1
}
Search(sum_islands);
}
return ;
} static int If_Valid(const int x, const int y)
{
/*If_Value函数:
功能:判断y位置是否被访问过
返回值:被访问过返回1,未被访问放回0,如果y是0,则就是基准情况,一定要给通过
*/
if (y == ) return ;
if (x&( << (y - ))) return ;
else return ;
} void Search(const int sum_islands)
{
int i, j, k, q, state_old;
long long tmp, ans1, ans2; if (sum_islands == )
{
printf("%d 1\n", islands_value[]);
return;
}
for (j = ; j <= sum_islands; j++)
{
dp[ << (j - )][j][] = islands_value[j];
num[ << (j - )][j][] = ;//初始化的时候价值为1
}
for (i = ; i < ( << sum_islands);i++)
{
for (j = ; j <= sum_islands; j++)
{
state_old = i ^ ( << (j - ));//得到当j还没有出现时候的位置
if (If_Valid(i, j))//这个位置就是要考虑的位置
{
for (k = ; k <= sum_islands; k++)
{
if (k != j && map[j][k] && If_Valid(i, k))
{
for (q = ; q <= sum_islands; q++)
{
if (!map[k][q] && q) continue;//q = 0的时候是没有意义的
if (q != j&&q != k
&& If_Valid(state_old, q)//是否是需要的q
&& dp[state_old][k][q] != -)//这个位置一定要有意义
{
tmp = islands_value[j] + islands_value[j] * islands_value[k] + dp[state_old][k][q];
if (map[j][q])
//假设j和q是联通的
tmp += islands_value[j] * islands_value[k] * islands_value[q];
if (tmp == dp[i][j][k])
//如果得到的结果是和ijk这个位置已经重复了,则自增(中间状态)
num[i][j][k] += num[state_old][k][q];
if (tmp > dp[i][j][k])
//如果比ijk这个状态还要大,则更新dp,继承num
{
dp[i][j][k] = tmp;
num[i][j][k] = num[state_old][k][q];
}
}
}
}
}
}
}
}
for (ans1 = -, ans2 = , j = ; j <= sum_islands; j++)
{
for (k = ; k <= sum_islands; k++)
{
if (k != j)
{
if (ans1 == dp[( << sum_islands) - ][j][k])
ans2 += num[( << sum_islands) - ][j][k];
if (ans1 < dp[( << sum_islands) - ][j][k])
{
ans1 = dp[( << sum_islands) - ][j][k];
ans2 = num[( << sum_islands) - ][j][k];
}
}
}
}
if (ans1 == -)
printf("0 0\n");
else
printf("%lld %lld\n", ans1, ans2 / );
}
DP:Islands and Bridges(POJ 2288)的更多相关文章
- 【状压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 ...
- POJ2288 Islands and Bridges
Description Given a map of islands and bridges that connect these islands, a Hamilton path, as we al ...
- poj 2288 Islands and Bridges ——状压DP
题目:http://poj.org/problem?id=2288 状压挺明显的: 一开始写了(记忆化)搜索,但一直T: #include<iostream> #include<cs ...
- poj 2288 Islands and Bridges——状压dp(哈密尔顿回路)
题目:http://poj.org/problem?id=2288 不知为什么记忆化搜索就是WA得不得了! #include<iostream> #include<cstdio> ...
- POJ 2288 Islands and Bridges(状压dp)
http://poj.org/problem?id=2288 题意: 有n个岛屿,每个岛屿有一个权值V,一条哈密顿路径C1,C2,...Cn的值为3部分之和: 第1部分,将路径中每个岛屿的权值累加起来 ...
- Islands and Bridges(POJ 2288状压dp)
题意:给你一个图和每个点的价值,边权值为连接两点权值的积,走哈密顿通路,若到达的点和上上个点相连则价值加三点乘积,求哈密顿通路的最大价值,和最大价值哈密顿通路的条数. 分析:开始看这个题很吓人,但想想 ...
- POJ 2288 Islands and Bridges (状压DP,变形)
题意: 给一个无向图,n个点m条边,每个点有点权,要求找到一条哈密顿路径,使得该路径的f(path)值最大.输出f值,若有多条最大f值的路径,输出路径数量. f值由如下3点累加而来: (1)所有点权之 ...
随机推荐
- 【CodeForces 624C】Graph and String
题 题意 n个表示abc三个字符的点,所有a和b是相连的,所有b和c是相连的,所有相同的是相连的,现在给你n个点和他们之间的m条边,判断是否存在这样的字符串,存在则给出一个符合条件的. 分析 我的做法 ...
- bzoj 3437 斜率优化DP
写题解之前首先要感谢妹子. 比较容易的斜率DP,设sum[i]=Σb[j],sum_[i]=Σb[j]*j,w[i]为第i个建立,前i个的代价. 那么就可以转移了. /**************** ...
- Angulajs系列-01-入门
1.解决什么问题? a, controller的各种的创建 b,体验angular的双向绑定 2.怎么解决 2.1 引入angularjs 下载地址 2.2 创建controller的方法 2.2.1 ...
- Ext comboBox的remote和local的区别
remote模式下不能使用模糊查询的功能 而local模式下可以实现模糊查询的功能 如果非要实现模糊查询的功能,最好就是提前把数据查询出来,缓存到本地,然后再用local模式 且,改个属性,改成可编辑 ...
- Spring学习3—控制反转(IOC)基于Annotation(注解)的依赖注入实现
一.依赖注入--手工装配—注解方式 在java代码中使用@Autowired或@Resource注解方式进行装配的前提条件是: 1.引入context命名空间 需要在xml配置文件中配置以下信息: ...
- Tomcat入门指南
转自javaresearch.com由timgball 整理 Tomcat是一个免费的开源Web服务器,最新版本是5.5.1,支持Servlet2.4,JSP2.0,非常适合初学者学习Java Web ...
- IDS IPS WAF之安全剖析
现在市场上的主流网络安全产品可以分为以下几个大类: 1.基础防火墙类,主要是可实现基本包过滤策略的防火墙,这类是有硬件处理.软件处理等,其主要功能实现是限制对IP:port的访问.基本上的实现都是默认 ...
- Cannot find class [org.apache.commons.dbcp.BasicDataSource]
错误:Cannot find class [org.apache.commons.dbcp.BasicDataSource] 原因:缺少commons-dbcp.jar
- Socket 学习入门
http://www.codeproject.com/Articles/13071/Programming-Windows-TCP-Sockets-in-C-for-the-Begin
- [Effective JavaScript 笔记]第17条:间接调用eval函数优于直接调用
eval函数不仅仅是一个函数.大多数函数只访问定义它们所在的作用域,而不能访问除此之外的作用域(词法作用域).eval函数具有访问调用它时的整个作用域的能力.编译器编写者首次设法优化js时,eval函 ...