博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
状压DP入门——玉米田题解
阅读量:5244 次
发布时间:2019-06-14

本文共 1447 字,大约阅读时间需要 4 分钟。

什么是状压DP:

状压DP就是一种能够把当前状态如用一个二进制数表示出来后作为动态规划的其中一个参数的DP方式。其实动态规划的本质就是由于题目中的某一些情况与之前的情况有所联系,而这个联系就是他们之间的动态转移方程。而用到状压DP的题目中的状态一般都是像这个玉米田这个题目中的一样连续一排中有些格子有玉米,有些格子没有玉米,这样导致我们可以使用一个二进制数来表示这一行玉米的种植情况,我们用1来表示这个格子上种了玉米,用0来表示这个格子上没有种玉米,假如我们这么种玉米:

1440436-20180803161639786-448795612.png
那么我们就可以用一个二进制数来表示这一行玉米的种植情况: 1010,在将这个二进制数转换为十进制数,得到一个十进制数x。这样我们就可以通过数x方便地表示这一行玉米的种植情况了。

之后我们用 $ f_{i,j} $ 来表示第\(i\) 行种植情况为 \(j\)的时候的方案数,之后我们就可以 发现 得到动态转移方程:

\[ f_{i,j}=\sum f_{i,k} (k为上一层的所有情况)\]

这样我们就可以从上一层的所有情况中递推了。

几个题目中需要用到的小技巧:

我们在这个题目中需要判断同一行中的种草的地方是不是相邻的,可以用这个东西判断

for(int i=0;i
>1))==0)) { check[i]=1; } }

如果当前状态的转换为十进制后为$ i $,那么当check[i]==1 的时候说明同一行种草的地方是不会有相邻的。

如果要判断这个地方中行与行间是不是有相邻的种草的地方,也可以用类似的方法,只需要判断上一个状态数 \(g\) 与当前状态数 \(j\)进行 AND运算后是不是会pow(2,n)-1就可以了

最后一个要注意的地方就是由于状压dp的下标值很大,所以记得开大数组

代码:

#include 
#include
#include
using namespace std;const int N = 15;const int mod = 1e8;int m,n;int p[N],check[5000];int tmp[N][5000];int map[N][N];int main(){ scanf("%d %d",&m,&n); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) scanf("%d",&map[i][j]); //储存每个农田状态 for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { p[i]=(p[i]<<1)+map[i][j]; } } int k=1<
>1))==0)) { check[i]=1; } } tmp[0][0]=1; for(int i=1;i<=m;i++) { for(int j=0;j

转载于:https://www.cnblogs.com/lixiao189/p/9414811.html

你可能感兴趣的文章
redis哨兵集群、docker入门
查看>>
hihoCoder 1233 : Boxes(盒子)
查看>>
oracle中anyData数据类型的使用实例
查看>>
C++对vector里面的元素排序及取任意重叠区间
查看>>
软件测试——性能测试总结
查看>>
12.4站立会议
查看>>
Java Concurrentmodificationexception异常原因和解决方法
查看>>
客户端访问浏览器的流程
查看>>
codeforces水题100道 第二十二题 Codeforces Beta Round #89 (Div. 2) A. String Task (strings)
查看>>
c++||template
查看>>
[BZOJ 5323][Jxoi2018]游戏
查看>>
编程面试的10大算法概念汇总
查看>>
Vue
查看>>
python-三级菜单和购物车程序
查看>>
条件断点 符号断点
查看>>
VMware12 + Ubuntu16.04 虚拟磁盘扩容
查看>>
水平垂直居中
查看>>
MySQL简介
查看>>
设计模式之桥接模式(Bridge)
查看>>
jquery的$(document).ready()和onload的加载顺序
查看>>