算法笔记-状压dp
状压dp
就是把状态压缩的dp
这样还是一种暴力但相对于纯暴力还是优雅的多。
实际上dp就是经过优化的暴力罢了
首先要了解位运算
给个链接吧
[https://blog.csdn.net/u013377068/article/details/81028453]
一些例题
之所以很难理解是因为没搞懂那些位运算的特点
在接下来的代码中会讲
poj 2411
[http://poj.org/problem?id=2411]
就是给你一个mn的网格,有两种砖12和2*1;
问你刚好填满的方案有多少
分析
首先你放置的时候会受到前一列影响,当前的放置也会队下一列有影响
假设你要放的位置有了就不能放了,再往下一行放
如果该位置没有就可以放一个12的,但它会对下一列有影响所以你得记录产生的影响
如果该位置没有且它下面也没有被占用就可以放一个21
之后你得跳到i+2行去放了 i是当前行
代码里说了很多关键的东西自己看吧
代码
#include<iostream>
#include<string.h>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
ll dp[15][2200];
int n,m;
//dp[i][j]//表示第i列状态为j时的方案数
void dfs(int i,int j,int state,int next){
//i表示行,j表示列,state表示当前状态,next表示到达下一列的状态
if(i==n){
//当前列已经到达第n+1行了
//下面有说 i是表示第i+1行的
dp[j+1][next]+=dp[j][state];
return;
}
else{
//如果当前列的当前行被占用过了往下一行搜索
if((state&(1<<i))){
//特别注意i是表示第i+1行的状态不是i行
//因为本来1在做好一位左移了i位它的位置在第i+1了,右边数起
dfs(i+1,j,state,next);
}
//如果当前格子没被占就可以放一个1*2,下一列就会改变状态
if((state&(1<<i))==0)
dfs(i+1,j,state,next|(1<<i));
//如果当前格子和下一行的格子都不被占用就可以放一个2*1下一列不会改变状态
//还得判断是否超出最下面那行
if(i+1<n&&(state&(1<<i))==0&&(state&(1<<(i+1)))==0)
dfs(i+2,j,state,next);
}
}
int main(){
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&m)&&(n+m)){
if(n>m) swap(n,m);
memset(dp,0,sizeof(dp));
dp[1][0]=1;
for(int i=1;i<=m;i++)
for(int j=0;j<(1<<n);j++)
if(dp[i][j]>0) dfs(0,i,j,0);//如果有某种状态转移到该状态才会进行填充
//第m列刚好填充满而且第m+1列是没有的才是答案
printf("%lld\n",dp[m+1][0]);
}
return 0;
}
poj 3254
[http://poj.org/problem?id=3254]
题意就是给你
一个矩阵 某个位置是0不可以种,1可以种
而且相邻的不能种也就是上下左右不能种
为你有多少种 种法
分析
对于某个位置该不该种你得看你左边和上边,因为我们是从第一列往右1列1列地选择种的方式不用考虑下面和左边
每一列的状态比如5=(101)表示该列的第一行和第三行都已经种了玉米,第二行没种
最后定义状态和转移方程
dp[i][j]表示第i列状态为j的方案数
dfs(int i,int j,int state,int next,bool flag)
//参数分别是行 列 状态 下一列状态 上一行是否种玉米
结果就是最后列所以状态之和
代码
#include<iostream>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
const int N=(1<<12)+10;
const int mod=1e8;
int a[20][20],dp[20][N];
//dp[i][j]表示第i列状态为j的方案数
int n,m;
void dfs(int i,int j,int state,int next,bool flag){
//参数分别是行 列 状态 下一列状态 上一行是否种玉米
//一定注意“”i表示的是第i+1行
if(i==n){
dp[j+1][next]=(dp[j+1][next]+dp[j][state])%mod;
return;
}
else{
//可以种,(i,j)这个位置为1,因为i表示的是第i+1行
//而实际中他的位置是a[i+1][j];
if(a[i+1][j]==1&&(state&(1<<i))==0&&flag==0){
//有两种选择种或者不种
dfs(i+1,j,state,next|(1<<i),1);
dfs(i+1,j,state,next,0);
}
else dfs(i+1,j,state,next,0);
}
}
int main(){
freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&m)){
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
memset(dp,0,sizeof(dp));
dp[1][0]=1;
for(int i=1;i<=m;i++)
for(int j=0;j<(1<<n);j++)
if(dp[i][j]>0)
dfs(0,i,j,0,0);
int sum=0;
for(int i=0;i<(1<<n);i++)
if(dp[m+1][i]>0)
sum=(sum+dp[m+1][i])%mod;
printf("%d\n",sum);
}
return 0;
}
算法笔记-状压dp的更多相关文章
- 【洛谷5492】[PKUWC2018] 随机算法(状压DP)
点此看题面 大致题意: 用随机算法求一张图的最大独立集:每次随机一个排列,从前到后枚举排列中的点,如果当前点加入点集中依然是独立集,就将当前点加入点集中,最终得到的点集就是最大独立集.求这个随机算法的 ...
- [学习笔记]状压dp
状压 \(dp\) 1.[SDOI2009]Bill的挑战 \(f[i][j]\) 表示匹配到字符串的第 \(i\) 位状态为 \(j\) 的方案数 那么方程就很明显了,每次枚举第 \(i\) 位的字 ...
- loj2540 「PKUWC2018」随机算法 【状压dp】
题目链接 loj2540 题解 有一个朴素三进制状压\(dp\),考虑当前点三种状态:没考虑过,被选入集合,被排除 就有了\(O(n3^{n})\)的转移 但这样不优,我们考虑优化状态 设\(f[i] ...
- 算法复习——状压dp
状压dp的核心在于,当我们不能通过表现单一的对象的状态来达到dp的最优子结构和无后效性原则时,我们可能保存多个元素的有关信息··这时候利用2进制的01来表示每个元素相关状态并将其压缩成2进制数就可以达 ...
- LOJ2540 [PKUWC2018] 随机算法 【状压DP】
题目分析: 听说这题考场上能被$ O(4^n) $的暴力水过,难不成出题人是毕姥爷? 首先思考一个显而易见的$ O(n^2*2^n) $的暴力DP.一般的DP都是考虑最近的加入了哪个点,然后删除后递归 ...
- 【51Nod】1920 空间统计学 状压DP
[题目]1920 空间统计学 [题意]给定m维空间中的n个点坐标,满足每一维坐标大小都在[0,3]之间,现在对于[0,3*m]的每个数字x统计曼哈顿距离为x的有序点对数.\(n \leq 2*10^5 ...
- 【BZOJ】2004: [Hnoi2010]Bus 公交线路 状压DP+矩阵快速幂
[题意]n个点等距排列在长度为n-1的直线上,初始点1~k都有一辆公车,每辆公车都需要一些停靠点,每个点至多只能被一辆公车停靠,且每辆公车相邻两个停靠点的距离至多为p,所有公车最后会停在n-k+1~n ...
- 「算法笔记」状压 DP
一.关于状压 dp 为了规避不确定性,我们将需要枚举的东西放入状态.当不确定性太多的时候,我们就需要将它们压进较少的维数内. 常见的状态: 天生二进制(开关.选与不选.是否出现--) 爆搜出状态,给它 ...
- 状压dp(状态压缩&&dp结合)学习笔记(持续更新)
嗯,作为一只蒟蒻,今天再次学习了状压dp(学习借鉴的博客) 但是,依旧懵逼·································· 这篇学习笔记是我个人对于状压dp的理解,如果有什么不对的 ...
随机推荐
- 第44章 添加新协议 - Identity Server 4 中文文档(v1.0.0)
除了对OpenID Connect和OAuth 2.0的内置支持之外,IdentityServer4还允许添加对其他协议的支持. 您可以将这些附加协议端点添加为中间件或使用例如MVC控制器.在这两种情 ...
- C# 处理PPT水印(一)——添加水印效果(文字水印、图片水印)
对文档添加水印可以有效声明和保护文档,是保护重要文件的方式之一.在PPT文档中同样也可以设置水印,包括文本水印和图片水印,本文将讲述如何通过Spire.Presentation for .NET来对P ...
- Java开发笔记(六十一)Lambda表达式
前面介绍了匿名内部类的简单用法,通过在sort方法中运用匿名内部类,不但能够简化代码数量,还能保持业务代码的连续性.只是匿名内部类的结构仍显啰嗦,虽然它省去了内部类的名称,但是花括号里面的方法定义代码 ...
- Spring笔记01_下载_概述_监听器
目录 Spring笔记01 1.Spring介绍 1.1 Spring概述 1.2 Spring好处 1.3 Spring结构体系 1.4 在项目中的架构 1.5 程序的耦合和解耦 2. Spring ...
- MySQL高级特性——绑定变量
从MySQL 4.1 版本开始,就支持服务器端的绑定变量,这大大提高了客户端和服务器端数据传输的效率 介绍 当创建一个绑定变量 SQL 时,客户端会向服务器发送一个SQL语句的原型.服务器端收到这个S ...
- sublime 使用快捷键
Goto Anything 快捷键 Ctrl+P (支持模糊匹配) 1,查找文件 在查找框中输入文件目录(知道目录直接输入目录,不知道目录直接输入页面名称即可.支持模糊匹配) index.ht ...
- 【代码笔记】Web-CSS-CSS 分组和嵌套
一, 效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...
- gulp前端自动化构建并上传oss
前言 前端自动化构建工具从最开始的grunt, gulp, fis等到现在比较流行的webpack可谓层出不穷,个人还是比较倾向于gulp,虽然有的时候会因为某个插件的配置问题头疼很久,但不可否认gu ...
- WebLogic使用总结
一. WebLogic安装 WebLogic使用总结(一)——WebLogic安装 一.下载WebLogic 到Oracle官网http://www.oracle.com/ 下载WebLogic(根据 ...
- Android为TV端助力 关于4.0之后不能直接获取SD卡外部存储路径的问题
Environment.getExternalStorageDirectory()是Android 2.x时代的产物,那时Android主流设备只有很小的内置存储器,然后都会外置一张sd卡,那时这个方 ...