明天计划上是要刷状压,但是作为现在还不会状压的\(ruoruo\)来说是一件非常苦逼的事情,所以提前学了一下状压\(dp\)。

鸣谢\(hmq\ juju\)的友情帮助

状态压缩动态规划

本博文的大体内容说明

因为刚学习状态压缩,并且刚做完一道例题。写博客的主要目的是怕自己忘掉,免得以后再重新学习一遍。而那些来踩我博客的同志们,希望以辩证的眼光来看待这篇博文。

于是这篇博客就讲\(Corn Fields\)这一道例题。所以阅读以下内容之前请先浏览一下题目。

基本原理

状态压缩\(dp\)主要是在二进制上进行状态转移的一种动态规划,因为每一个十进制的数可以表示成二进制,所以我们每一行的状态用一个十进制的数来储存。

状态压缩\(dp\)的主要工具

因为状态是在二进制上进行转移的,所以我们需要用到一些位运算来帮助我们进行状态转移。

  • |符号,表示或运算,0|1=1,1|1=1,1|0=1,0|0=0。
  • &符号,表示与运算,0&1=0,1&1=1,1&0=0,0&0=0。
  • 符号,表示异或运算,01=1,11=0,10=1,0^0=0。
  • <<符号,表示在2进制下小数点向右移动若干位,1<<2=4,3<<1=6。
  • >>符号,表示在2进制下小数点向左移动若干位,2>>1=1,13>>3=1。
  • 判断数字x第i位是否是1——if (x&(1<<i))。
  • 将一个数字x第i位改变为1——x|=(1<<i)。

状态压缩\(dp\)实现的基本过程

  1. 首先枚举所有的情况。根据题意,\(1\)表示有草,\(0\)表示没草,然后又有\(n\)位,所以我们就枚举\(0\sim2^n\)的位数,为啥尼?

    因为\(0\)表示没有草的情况,而\(2^n\)也就是\(\begin{matrix} \underbrace{ 1\cdots1 } \\ n\end{matrix}\)这种全是草的情况,所以要这样枚举。然后我们在存储合法状态,存到\(state\)数组里。
  2. 枚举完之后,我们的所有情况出来了,我们要进行存图,存图也要用二进制。这里我们存图用一个\(cur\)数组,这个数组表示图的存储,为了方便,我们将无草转变为\(1\),有草为\(0\)。
  3. 然后就是进行状态存储。我们已经有了合法状态,我们也有图,我们就要枚举判断合法状态内的可行状态。

    这里我们要用到一个\(fit\)函数。fit函数可以帮助我们判断合不合理,然后找到可行状态
  4. 状态转移。设\(dp[i][j]\)表示第\(i\)行的第\(j\)个状态。

    状态转移要枚举上一层的状态。然后方程很简单\(dp[i][j]=dp[i][j]+dp[i-1][k]\)。

例题代码讲解

首先我们看一下如何枚举状态

inline void init()//初始化
{
int sum=1<<n,i;//列举可能状态,并预存
for (i=0;i<sum;i++)
if (!(i&(i<<1)))//枚举合法状态
state[++tot]=i;
}

为什么\(!(i\&(i<<1))\)呢,因为你只要有牧草重叠,这个数绝对不会为\(0\)。

然后看一下图的存储

    for (i=1;i<=m;i++)
for (j=1;j<=n;j++)
{
k=read();
if (!k)
cur[i]+=(1<<(n-j));
}

为啥是左移\(n-j\)为呢\(?\)

因为你是从右往左来储存二进制的,第\(j\)位如果反过来肯定是第\(n-j\)位咯。

\(fit\)函数

inline bool fit(int x,int k)//判断当前状态是否符合当前行
{
return !(state[x]&cur[k]);
}

只要这一个函数理解了,状压就基本搞定了。

因为\(state\)存储的是合法状态,\(cur\)存储的是不合法状态,所以两者按位与,合法状态的数一定为\(0\),不合法状态的数一定不为\(0\)。这里有的同志就开始疑惑了,为啥尼?

你想想\(state\)里面\(1\)为有草,\(cur\)里面\(1\)为无草,而\(1\&1\)则代表有值,那么这个方案可行吗?

就这样我们能进行第一行的初始化咯

    for (i=1;i<=tot;i++)//初始化第一行
if (fit(i,1))
dp[1][i]=1;

状态转移

状态转移相对来说就比较简单了。

    for (i=2;i<=m;i++)//枚举行
for (j=1;j<=tot;j++)//枚举当前状态
{
if (!fit(j,i))//如果这一层的方案不在可行方案里
continue;
for (k=1;k<=tot;k++)//枚举上一层可行状态
{
if (!fit(k,i-1))//如果这一层的方案不在可行方案里
continue;
if (state[j]&state[k])//如果上一层的可行方案与这一层可行方案冲突,意思是上下有草挨着
continue;
dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;//状态转移
}
}

具体可能的疑问都在代码中注释了

第一层枚举行数,第二层枚举可行方案,第三层枚举上一层的可行方案,万事大吉!

代码

#include<cstdio>
#include<iostream>
#include<cctype>
#define mod 100000000
#define C continue//懒得打hhhhh
using namespace std;
int n,m,tot,state[1500],dp[15][1500],ans,cur[15];//dp表示当前最大值,第一维是行数,第二维是状态数,cur是每行的情况,state是预存的可能状态
inline int read()//读入优化
{
int x=0,f=1;
char c=getchar();
while (!isdigit(c))
f=c=='-'?-1:1,c=getchar();
while (isdigit(c))
x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
} inline bool fit(int x,int k)//判断当前状态是否符合当前行
{
return !(state[x]&cur[k]);
} inline void init()//初始化
{
int sum=1<<n,i;//列举可能状态,并预存
for (i=0;i<sum;i++)
if (!(i&(i<<1)))//枚举合法状态
state[++tot]=i;
}
int main()
{
int i,j,k;
m=read();
n=read();
init();
for (i=1;i<=m;i++)
for (j=1;j<=n;j++)
{
k=read();
if (!k)
cur[i]+=(1<<(n-j));
}
for (i=1;i<=tot;i++)//初始化第一行
if (fit(i,1))
dp[1][i]=1;
for (i=2;i<=m;i++)//枚举行
for (j=1;j<=tot;j++)//枚举当前状态
{
if (!fit(j,i))//如果这一层的方案不在可行方案里
continue;
for (k=1;k<=tot;k++)//枚举上一层可行状态
{
if (!fit(k,i-1))//如果这一层的方案不在可行方案里
continue;
if (state[j]&state[k])//如果上一层的可行方案与这一层可行方案冲突,意思是上下有草挨着
continue;
dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;//状态转移
}
}
for (i=1;i<=tot;i++)
ans=(ans+dp[m][i])%mod;
printf("%d",ans);
return 0;
}

状态压缩dp初学__$Corn Fields$的更多相关文章

  1. 【原创】【状态压缩DP】POJ3254 Corn Fields【新手向】

    一开始根本不会状压dp,上网各种找题解,但发现他们写的都很......反正我作为一个没有接触过状态压缩的,根本看不懂! 然后看了好多状态压缩的题的题解,总结了一下思路,思路很重要,有了思路转换成计算机 ...

  2. POJ 3254 Corn Fields(状态压缩DP)

    Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4739   Accepted: 2506 Descr ...

  3. POJ3254 - Corn Fields(状态压缩DP)

    题目大意 给定一个N*M大小的土地,土地有肥沃和贫瘠之分(每个单位土地用0,1来表示贫瘠和肥沃),要求你在肥沃的单位土地上种玉米,如果在某个单位土地上种了玉米,那么与它相邻的四个单位土地是不允许种玉米 ...

  4. POJ 3254 Corn Fields (状态压缩DP)

    题意:在由方格组成的矩形里面种草,相邻方格不能都种草,有障碍的地方不能种草,问有多少种种草方案(不种也算一种方案). 分析:方格边长范围只有12,用状态压缩dp好解决. 预处理:每一行的障碍用一个状态 ...

  5. 【bzoj1725】[USACO2006 Nov]Corn Fields牧场的安排 状态压缩dp

    题目描述 Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地.FJ打算在牧场上的某几格土 ...

  6. POJ Corn Fields 状态压缩DP基础题

    题目链接:http://poj.org/problem?id=3254 题目大意(名称什么的可能不一样,不过表达的意思还是一样的): 种玉米 王小二从小学一年级到现在每次考试都是班级倒数第一名,他的爸 ...

  7. 状压DP POJ 3254 Corn Fields

    题目传送门 /* 状态压缩DP:先处理硬性条件即不能种植的,然后处理左右不相邻的, 接着就是相邻两行查询所有可行的种数并累加 写错一个地方差错N久:) 详细解释:http://www.tuicool. ...

  8. POJ3254(入门状态压缩dp)

    Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13203   Accepted: 6921 Desc ...

  9. 关于状态压缩DP以及状态压缩

    首先要明确:状态压缩是利用数字来代表一组序列的方法,从而降低序列访问的复杂度,本质上跟HASH有着差不多的思想,但是其实就是数位运算的一种 定义:集合中共有N个数字,其中每个数字均小于K,能么我们可以 ...

随机推荐

  1. NHibernate3剖析:Query篇之NHibernate.Linq增强查询

    系列引入 NHibernate3.0剖析系列分别从Configuration篇.Mapping篇.Query篇.Session策略篇.应用篇等方面全面揭示NHibernate3.0新特性和应用及其各种 ...

  2. JAVA性能优化的五种方式

    一,JAVA性能优化之设计优化 设计优化处于性能优化手段的上层.它往往须要在软件开发之前进行.在软件开发之前,系统架构师应该就评估系统可能存在的各种潜在问题和技术难点,并给出合理的设计方案,因为软件设 ...

  3. yolo源码解析(2):处理图片

    首先安装ffmpeg, 参考https://blog.csdn.net/lwgkzl/article/details/77836207 然后将视频切分为图片, 参考:https://zhuanlan. ...

  4. xBIM 高级01 IFC多模型合并

    系列目录    [已更新最新开发文章,点击查看详细]  多模型合并可以实现以下功能: 覆盖多个模型以表现得像一个模型 统一访问数据,就像它是单个模型一样 只读.要修改模型的内容,您必须使用特定模型 不 ...

  5. WPF 基础

    关于布局的规则 控件的布局应该由容器来决定,而不是通过自身使用margin之类的东西来控制位置 避免为控件定义明确的尺寸,但应该限定一个可接受的最大及最小尺寸 不要将界面元素设置成与屏幕坐标相关 容器 ...

  6. tabIndex-bootstrap中Get到的

    网页键盘的无障碍访问性 其实加了这个,可以控制Tab键切换的顺序,聚焦等 这个属性,任何标签都可以添加,没有兼容性限制,属性值的范围:0-32767 当一个元素设置tabindex属性值为-1的时候, ...

  7. vmware workstation pro 14 虚拟机无法开启、黑屏的解决方案汇总

    方案1:卸载鲁大师,重启. 方案2:管理员命令行,输入netsh winsock reset,重启. 方案3:360安全管家修复LSP,重启. 方案4:卸载14.0,安装12.0,手动导入虚拟机.

  8. centos下nginx配置

    转自  http://www.linuxidc.com/Linux/2016-09/134907.htm 安装所需环境 Nginx 是 C语言 开发,建议在 Linux 上运行,当然,也可以安装 Wi ...

  9. easyui的datagrid右侧没有边框线

    做项目时,用的easyui的框架的datagrid,运行时发现右侧没有边框,其它的都有边框,使用网页的审查元素可以看到datagrid样式里的宽度没有自动减去2个像素,这些都是easyui自算的宽高, ...

  10. Servicification

    Servicification Summary The Chromium codebase now supports many platforms and use cases. In response ...