CH0103最短Hamilton路径 & poj2288 Islands and Brigdes【状压DP】
虐狗宝典学习笔记:
取出整数\(n\)在二进制表示下的第\(k\)位 \((n >> k) & 1)\)
取出整数\(n\)在二进制表示下的第\(0 ~ k - 1\)位(后\(k\)位) \(n & ((1 << k) - 1)\)
把整数\(n\)在二进制表示下的第\(k\)位取反 \(n xor (1 << k)\)
对整数\(n\)在二进制表示下的第\(k\)为赋值\(1\) \(n | (1 << k)\)
对整数\(n\)在二进制表示下的第\(k\)位赋值\(0\) \(n & (~(1 << k))\)
CH0103---最短Hamilton路径
题意:
hamilton指的是每个节点经过一次且仅经过一次的路径。现在路径上有权值,问最短的路径长度。
思路:
状压dp。\(dp[i][j]\)表示在状态是\(i\)且最后一个经过的点时\(j\)时的最短路径长度。
\(dp[i][j] = min{dp[i xor (i << j)][k] + weight(k, j)}\)
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL; int n;
int g[][];
int dp[ << ][]; int main()
{
scanf("%d", &n);
memset(dp, 0x3f, sizeof(dp));
for(int i = ; i < n; i++){
for(int j = ; j < n; j++){
scanf("%d", &g[i][j]);
}
}
dp[][] = ;
for(int i = ; i < << n; i++){
for(int j = ; j < n; j++){
if(i >> j & ){
for(int k = ; k < n; k++){
if((i ^ << j) >> k & ){
dp[i][j] = min(dp[i][j], dp[i ^ << j][k] + g[k][j]);
}
}
}
}
} printf("%d\n", dp[( << n) - ][n - ]);
return ;
}
poj2288---Islands and Bridges
http://poj.org/problem?id=2288
题意:
有n个岛,m座桥。每座岛有一个val,一条汉密尔顿路径的值是路径中所有点的val之和,加上所有路径上相邻的两个岛的val乘积之和,加上路径上相邻的三个岛的val乘积之和。求最大的值以及方案数。
思路:
和CH0103很相近,不同的是这道题要多存一个岛。\(dp[stat][i][j]\)表示当前状态是\(stat\),最后一个走的岛是\(j\),倒数第二个走的岛是\(i\), \(num\)数组表示对应的方案数。
当\( (stat, i, j) \)可达时,我们检查下一个要走的岛\(k\),如果此时\( (stat >> k) & 1 == 0 \) 且 \( g[j][k] == 1 \)说明\(k\)是满足条件的
设\(tmp\)是下一个走\(k\)时的总价值。那么,\(dp[stat | (1 << k)][j][k] = max(dp[stat | (1 << k)][j][k], tmp)\)
如果\(tmp == dp[stat | (1 << k)][j][k]\),那么,\(num[stat | (1 << k)][j][k] += num[stat][i][j]\)。否则\(num[stat | (1 << k)][j][k] = num[stat][i][j] \)
那么要如何求\(tmp\) 呢。
首先当\(j\)可以走到\(k\)时,肯定有 \(tmp = dp[stat][i][j] + val[k] + val[j] * val[k] \)
如果此时还有\(g[i][k] == 1\) 那么\(tmp += val[i] * val[j] * val[k]\)
最后我们对于\(stat = (1 << n) - 1\)枚举\(i\)和\(j\),找到最大的结果。
注意方案数会超出int。还需要注意\(n = 1\)时的特殊情况。
注意内存省着点,会MLE
//#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL; int n, m, q;
bool g[][];
int dp[ << ][][];
LL num[ << ][][];
int val[];
int cnt; void hamilton()
{
memset(dp, -, sizeof(dp));
memset(num, , sizeof(num));
for(int i = ; i < n; i++){
for(int j = ; j < n; j++){
if(g[i][j]){
dp[ << i | << j][i][j] = val[i] + val[j] + val[i] * val[j];
num[ << i | << j][i][j] = ;
}
}
} for(int stat = ; stat < << n; stat++){
for(int i = ; i < n; i++){
if((stat >> i) & ){
for(int j = ; j < n; j++){
if((stat >> j) & ){
if(g[i][j] && dp[stat][i][j] != -){
for(int k = ; k < n; k++){
if(g[j][k] && k != i && ((stat >> k) & ) == ){
int tmp = dp[stat][i][j] + val[k] + val[k] * val[j];
if(g[i][k]){
tmp += val[i] * val[j] * val[k];
}
if(tmp > dp[stat | ( << k)][j][k]){
dp[stat | ( << k)][j][k] = tmp;
num[stat | ( << k)][j][k] = num[stat][i][j];
}
else if(tmp == dp[stat | ( << k)][j][k]){
num[stat | ( << k)][j][k] += num[stat][i][j];
}
}
}
}
}
}
}
}
}
//return dp[(1 << n) - 1][n - 1];
} int main()
{
scanf("%d", &q);
while(q--){
memset(g, , sizeof(g));
scanf("%d%d", &n, &m);
for(int i = ; i < n; i++){
scanf("%d", &val[i]);
}
for(int i = ; i < m; i++){
int u, v;
scanf("%d%d", &u, &v);
g[u - ][v - ] = ;
g[v - ][u - ] = ;
}
if(n == ){
printf("%d 1\n", val[]);
continue;
} hamilton();
int maxi = ;
LL ans = ;
for(int i = ; i < n; i++){
for(int j = ; j < n; j++){
if(g[i][j]){
if(maxi < dp[( << n) - ][i][j]){
maxi = dp[( << n) - ][i][j];
ans = num[( << n) - ][i][j];
}
else if(maxi == dp[( << n) - ][i][j]){
ans += num[( << n) - ][i][j];
}
}
}
} printf("%d %lld\n", maxi, ans / );
}
return ;
}
CH0103最短Hamilton路径 & poj2288 Islands and Brigdes【状压DP】的更多相关文章
- [poj2288] Islands and Bridges (状压dp)
Description Given a map of islands and bridges that connect these islands, a Hamilton path, as we al ...
- CH0103 最短Hamilton路径 dp
正解:状压dp 解题报告: 完了吃枣退役:D 我是真的没想到这是个dp...脑子越来越不好了,大概是太久没碰OI了都要生疏了...哭了,感觉自己太傻逼了可能不适合学信息... 知道是个状压dp就eas ...
- 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> ...
- 『最短Hamilton路径 状态压缩DP』
状压DP入门 最短Hamilton路径 Description 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Hamil ...
- 最短Hamilton路径【状压DP】
给定一张 nn 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每个点恰好一次. 输入 ...
- 位运算 - 最短Hamilton路径
给定一张 n 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每个点恰好一次. 输入格 ...
- 0103 最短Hamilton路径【状压DP】
0103 最短Hamilton路径 0x00「基本算法」例题 描述 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Ham ...
- 最短Hamilton路径
题目描述 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每 ...
随机推荐
- vuejs使用FormData对象,ajax上传图片文件
我相信很多使用vuejs的朋友,都有采用ajax上传图片的需求,因为前后端分离后,我们希望都能用ajax来解决数据问题,传统的表单提交会导致提交成功后页面跳转,而使用ajax能够无刷新上传图片等文件. ...
- LHC大神问的矩阵转置问题
数学中线性代数中提到的矩阵转置,其实在我们的业务场景中也有需要的地方,比如LHC大神问到的这个问题 那么如何进行行列转换呢? 代码如下: <?php $array=array( '部门1'=&g ...
- IE8兼容性调试及IE 8 css hack
做网站开发,一提到IE,就会让人头大,有一肚子的牢骚要发:微软为什么不跟着国际标准走呢,总是独树一帜,搞出那么多问题来.IE的firebug调试工具也不太好用,尤其是低版本的IE,更是让人头疼. 最近 ...
- 【Android】amr文件时长
一.文件时长获取 String curAudioFile = “XXX.amr”; MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.s ...
- 【代码审计】iZhanCMS_v2.1 前台IndexController.php页面存在SQL注入 漏洞分析
0x00 环境准备 iZhanCMS官网:http://www.izhancms.com 网站源码版本:爱站CMS(zend6.0) V2.1 程序源码下载:http://www.izhancms ...
- 【RF库Collections测试】Log Dictionary 【同log list】
Name:Log DictionarySource:Collections <test library>Arguments:[ dictionary | level=INFO ]Logs ...
- Create maintenance backup plan in SQL Server 2008 R2 using the wizard
You will need to identify how you want your maintenance plan to be setup. In this example the mainte ...
- osg使用shader动态修改纹理坐标
#include <osg/Node> #include <osg/Geometry> #include <osg/Notify> #include <osg ...
- 如何构建日均千万PV Web站点 (三) Sharding
其实国内许多大型网站为了应对日益复杂的业务场景,通过使用分而治之的手段将整个网站业务分成不同的产品线,比如说国内那些大型购物交易网站它们都将自己的网站首页.商铺.订单.买家.卖家等拆分不同的产品线,分 ...
- iOS 静态库和动态库(库详解)
什么是库 ? 库就是程序代码的集合,将N个文件组织起来,是共享程序代码的一种方式.库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行. 库的分类 开源库:源代码是公开的,可以看到每个实现 ...