题目链接:https://vjudge.net/contest/224636#problem/G

转载于:https://blog.csdn.net/harrypoirot/article/details/23163485

题目大意:

农夫有一块地,被划分为m行n列大小相等的格子,其中一些格子是可以放牧的(用1标记),农夫可以在这些格子里放牛,其他格子则不能放牛(用0标记),并且要求不可以使相邻格子都有牛。现在输入数据给出这块地的大小及可否放牧的情况,求该农夫有多少种放牧方案可以选择(注意:任何格子都不放也是一种选择,不要忘记考虑!

解题分析就看上面那篇博客,我也是照着上面学的。

#include <cstdio>
#include <cstring>
using namespace std; #define mod 100000000
int M, N, top = ;
//top表示每行最多的状态数 int state[];
//state存放每行所有的可行状态(即没有相邻的状态) int dp[][];
//dp[i][j]:对于前i行数据,第i行有前j种可能状态时的解
int cur[];
//cur[i]表示的是第i行整行的情况 inline bool ok(int x) { //判断状态x是否可行
if (x&x << ) return false;//若存在相邻两个格子都为1,则该状态不可行
return true;
} void init() { //遍历所有可能的状态
top = ;
int total = << N; //遍历状态的上界
for (int i = ; i < total; ++i) { //总共有total种状态需要讨论
if (ok(i))state[++top] = i; //state[]为一行中所有可行的状态
}
}
//原理就是,如果你在不能够放1的位置放了1,那么这个方案肯定不可行
inline bool fit(int x, int k) { //判断状态x 与第k行的实际状态的逆是否有‘重合’ //判断理论上每一行能符合的情况是否与某一特定的行符合,因为每一行规定了能放1的位置
if (x&cur[k])return false; //若有重合,(即x不符合要求)
return true; //若没有,则可行
} int main() {
while (scanf("%d%d", &M, &N) != EOF) {
init();
memset(dp, , sizeof(dp));
for (int i = ; i <= M; ++i) {
cur[i] = ;
int num;
for (int j = ; j <= N; ++j) { //输入时就要按位来存储,cur[i]表示的是第i行整行的情况,每次改变该数字的二进制表示的一位
scanf("%d", &num); //表示第i行第j列的情况(0或1)
if (num == ) //若该格为0
cur[i] += ( << (N - j)); //则将该位置为1(注意要以相反方式存储,即1表示不可放牧
} //cur[]数组,利用状态压缩,用一维数组,表示了二维的数据
}
for (int i = ; i <= top; i++) {
if (fit(state[i], )) { //判断所有可能状态与第一行的实际状态的逆是否有重合
dp[][i] = ; //若第1行的状态与第i种可行状态吻合,则dp[1][i]记为1
}
} //先算出第一行的情况,初始化dp[1][]的所有情况,方便下面dp的递推, //前面的都是准备工作,都是为了下面的这个状态转移方程做准备 for (int i = ; i <= M; ++i) { //i索引第2行到第M行
for (int k = ; k <= top; ++k) { //该循环针对所有可能的状态,找出一组与第i行相符的state[k]
if (!fit(state[k], i))continue; //判断是否符合第i行实际情况
for (int j = ; j <= top; ++j) { //找到state[k]后,再找一组与第i-1行符合,且与第i行(state[])不冲突的状态state[j]
if (!fit(state[j], i - ))continue; //判断是否符合第i-1行实际情况 //找出上一行的所有可行状态
if (state[k] & state[j])continue; //判断是否与第i行冲突 //判断第i行的状态是否与上一行冲突
dp[i][k] = (dp[i][k] + dp[i - ][j]) % mod; //若以上皆可通过,则将'j'累加到‘k'上
} //这里就相当于dp[i][k]+=dp[i-1][j],只不过因为要取模运算,所以写成这样
} //状态转移方程的根据为,dp[i][k]表示第i行采用方案k时,前i总共有多少种可行的情况
}
int ans = ;
for (int i = ; i <= top; ++i) { //累加最后一行所有可能状态的值,即得最终结果!!!
ans = (ans + dp[M][i]) % mod;
}
printf("%d\n", ans);
}
}

2018-07-26

Poj - 3254 Corn Fields (状压DP)(入门)的更多相关文章

  1. poj 3254 Corn Fields 状压dp入门

    题目链接 题意 在\(M\times N\)的\(0,1\)格子上放东西,只有标记为\(1\)的格子可以放东西,且相邻的格子不能同时放东西.问有多少种放法. 思路 参考:swallowblank. \ ...

  2. POJ 3254 Corn Fields (状压dp)

    题目链接:http://poj.org/problem?id=3254 给你n*m的菜地,其中1是可以种菜的,而菜与菜之间不能相邻.问有多少种情况. 状压dp入门题,将可以种菜的状态用一个数的二进制表 ...

  3. POJ 3254 - Corn Fields - [状压DP水题]

    题目链接:http://poj.org/problem?id=3254 Time Limit: 2000MS Memory Limit: 65536K Description Farmer John ...

  4. [ An Ac a Day ^_^ ] POJ 3254 Corn Fields 状压dp

    题意: 有一块n*m的土地 0代表不肥沃不可以放牛 1代表肥沃可以放牛 且相邻的草地不能同时放牛 问最多有多少种放牛的方法并对1e8取模 思路: 典型的状压dp 能状态压缩 能状态转移 能状态压缩的题 ...

  5. POJ 1684 Corn Fields(状压dp)

    描述 Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ ...

  6. POJ 3254 Corn Fields (状压入门)

    Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M≤ 12; 1 ≤ N ≤ 12) ...

  7. poj - 3254 Corn Fields (状态压缩dp入门)

    http://poj.org/problem?id=3254 参考:http://blog.csdn.net/accry/article/details/6607703 农夫想在m*n的土地上种玉米, ...

  8. P1879 [USACO06NOV]玉米田Corn Fields (状压dp入门)

    题目链接: https://www.luogu.org/problemnew/show/P1879 具体思路: 我们可以先把所有合法的情况枚举出来,然后对第一行判断有多少种情况满足,然后对于剩下的行数 ...

  9. 【POJ3254】Corn Fields 状压DP第一次

    !!!!!!! 第一次学状压DP,其实就是运用位运算来实现一些比较,挺神奇的.. 为什么要发“!!!”因为!x&y和!(x&y)..感受一下.. #include <iostre ...

随机推荐

  1. Activity生命周期函数、onSaveInstanceState()和onRestoreInstanceState()的介绍

    http://www.cnblogs.com/tianzhijiexian/p/3885472.html

  2. [转]python 装饰器

    以前你有没有这样一段经历:很久之前你写过一个函数,现在你突然有了个想法就是你想看看,以前那个函数在你数据集上的运行时间是多少,这时候你可以修改之前代码为它加上计时的功能,但是这样的话是不是还要大体读读 ...

  3. 教你如何使用android studio发布release 版本【转】

    原文链接 想必还有人对如何在Android studio (以下简称as)发布release版本的app而狂刷百度吧?都是过来人,我很理解这种心情,百度到的基本是半成品,为什么这么说呢?百度一下,你就 ...

  4. HTML学习笔记06-连接

    HTML超链接 HTML使用标签<a>来设置文本超链接. 超链接可以是文字,也可以是图片,点击这些内容跳转到新的文档或当前文档的某个部分 代码类似这样: <a href=" ...

  5. 研究slatstack时踩过的坑,注意点及解决方案

    运行问题 1.直接物理性移除minion或者更换minion原先连接的master,会导致先前的master始终无法ping通minion [root@localhost salt]# salt '* ...

  6. javaScript——原型继承四步曲

    <script> //js模拟类的创建以及继承 //第一步:创建父类 function Parent(name){ this.name = name; } //给父类添加属性方法 Pare ...

  7. ThinkPHP 3.1,3.2中对IN和BETWEEN正则匹配不当导致的一个SQLi

    // where子单元分析 protected function parseWhereItem($key,$val) { $whereStr = ''; if(is_array($val)) { if ...

  8. Java桌面程序打包成exe可执行文件

    前言: 我们都知道Java可以将二进制程序打包成可执行jar文件,双击这个jar和双击exe效果是一样一样的,但感觉还是不同.其实将java程序打包成exe也需要这个可执行jar文件. 准备: ecl ...

  9. liunx rm 命令修改

    原文:https://blog.csdn.net/Ace_Shiyuan/article/details/60139791 1.打开一个终端,输入命令:vim ~/.bashrc Linux下修改rm ...

  10. cf789c

    主要是线性时间内求最大连续和 #include<bits/stdc++.h> using namespace std; #define maxn 200005 #define ll lon ...