虐狗宝典学习笔记:

取出整数\(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路径

http://contest-hunter.org:83/contest/0x00%E3%80%8C%E5%9F%BA%E6%9C%AC%E7%AE%97%E6%B3%95%E3%80%8D%E4%BE%8B%E9%A2%98/0103%20%E6%9C%80%E7%9F%ADHamilton%E8%B7%AF%E5%BE%84

题意:

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】的更多相关文章

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

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

  2. CH0103 最短Hamilton路径 dp

    正解:状压dp 解题报告: 完了吃枣退役:D 我是真的没想到这是个dp...脑子越来越不好了,大概是太久没碰OI了都要生疏了...哭了,感觉自己太傻逼了可能不适合学信息... 知道是个状压dp就eas ...

  3. poj 2288 Islands and Bridges ——状压DP

    题目:http://poj.org/problem?id=2288 状压挺明显的: 一开始写了(记忆化)搜索,但一直T: #include<iostream> #include<cs ...

  4. poj 2288 Islands and Bridges——状压dp(哈密尔顿回路)

    题目:http://poj.org/problem?id=2288 不知为什么记忆化搜索就是WA得不得了! #include<iostream> #include<cstdio> ...

  5. 『最短Hamilton路径 状态压缩DP』

    状压DP入门 最短Hamilton路径 Description 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Hamil ...

  6. 最短Hamilton路径【状压DP】

    给定一张 nn 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每个点恰好一次. 输入 ...

  7. 位运算 - 最短Hamilton路径

    给定一张 n 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每个点恰好一次. 输入格 ...

  8. 0103 最短Hamilton路径【状压DP】

    0103 最短Hamilton路径 0x00「基本算法」例题 描述 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Ham ...

  9. 最短Hamilton路径

    题目描述 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每 ...

随机推荐

  1. 给树莓派安装看门狗的两种方法,二代B

    树莓派的CPU是保护有硬件看门狗的,可以通过安装模块和值守程序来实现看门狗防止树莓派死机. 安装方法一:watchdog.sh的源码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...

  2. vue时间格式化

    export function formatTime(date, fmt) { if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (date.g ...

  3. 【应用安全】微软的安全开发生命周期(SDL)

    0x01 SDL介绍 安全开发生命周期(SDL)即Security Development Lifecycle,是一个帮助开发人员构建更安全的软件和解决安全合规要求的同时降低开发成本的软件开发过程. ...

  4. 【RF库Collections测试】Sort List

    Name:Sort ListSource:Collections <test library>Arguments:[ list_ ]Sorts the given list in plac ...

  5. SpringBoot(七)-- 启动加载数据

    一.场景 实际应用中,我们会有在项目服务启动的时候就去加载一些数据或做一些事情这样的需求.为了解决这样的问题,spring Boot 为我们提供了一个方法,通过实现接口 CommandLineRunn ...

  6. mybatis 之 resultType="Integer"

    public class EcPromoteRuleAdditionalNew extends BaseBO { private String[] promoteRuleIds; public Str ...

  7. tomcat端口被占用的两个解决方法

    tomcat 的 8080 端口经常会被占用,解决办法两个: 1.关闭占用8080端口的进程:8080端口被占用的话执行startup.bat会报错,可在cmd下执行netstat -ano命令查看8 ...

  8. iOS - 截屏,view截图的基本方法

    推荐一个第三方好用的框架:SDScreenshotCapture #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice cur ...

  9. HTML5实现图片预览功能

    两种方式实现 URL FileReader Index.jsp文件 <%@page contentType="text/html" pageEncoding="UT ...

  10. 浅析TCP字节流与UDP数据报的区别

    转自http://www.linuxidc.com/Linux/2014-11/109545.htm “TCP是一种流模式的协议,UDP是一种数据报模式的协议”,这句话相信大家对这句话已经耳熟能详~但 ...