题目链接:http://poj.org/problem?id=3254

题目大意:Farmer John 放牧cow,有些草地上的草是不能吃的,用0表示,然后规定两头牛不能相邻放牧。问你有多少种放牧方法。

Sample Input

2 3
1 1 1
0 1 0

Sample Output

9

分析:对于这种二维地图型,一般设状态dp[i][j]表示第 i 行第 j 状态达到要求的总数

  输入地图,用map[i]表示第 i 行中的状态。为了是sta[k]表示可行状态更加方便,map[i]中用0表示可放牧,1表示不可放牧,这样如果(sta[k]&map[i]==0)则说明满足放牧要求。

  动态规划:初始化:令dp[0][j]中可以在第一行放牧的状态j,dp[0][j]=1;

      转移方程:dp[i][j] = dp[i][j] + dp[i-1][k],k为所有满足条件的状态

代码如下:

 # include<stdio.h>
# include<string.h>
const int MAXN = <<;
const int MOD = ;
int sta[MAXN],num;
int dp[][MAXN]; //dp[i][j]表示第i行在集合j中满足条件的方案数
int map[]; //表示输入中每一行的状态
int n,m;
void init(){
num =;
int sum = <<m;
for(int i=; i<sum;i++) //从1到sum里边有满足该状态中放牛的位置不相邻的方案有num个
if(i&(i<<))
continue;
else
sta[num++] = i;
} void DP(){
int i,j,k;
for(i=; i<num; i++)
if(!(sta[i]&map[])) //寻找第一层满足条件的方案,令它为1
dp[][i] = ;
for(i=; i<n; i++)
for(j=; j<num; j++) //第i行是状态j
if(sta[j]&map[i]) //去掉与草场矛盾
continue;
else
for(k=; k<num; k++){ //第i-1行是状态k
if(map[i-]&sta[k]) //去掉与草场矛盾的
continue;
if(sta[k]&sta[j]) //去掉与上一行状态矛盾的
continue;
dp[i][j] = (dp[i][j] + dp[i-][k]) % MOD;
}
int ans = ;
for(i=; i<num; i++)
ans = (ans+dp[n-][i])%MOD;
printf("%d\n",ans);
}
int main(){
int i,j,temp;
while(scanf("%d%d",&n,&m)!=EOF){
memset(map,,sizeof(map));
for(i=; i<n; i++)
for(j=; j<m; j++){
scanf("%d",&temp);
if(temp==) //将每行状态二进制表示,1代表题目中的0,代表1
map[i] += <<(m-j-);
}
init();
DP();
}
return ;
}

 也可以使用滚动数组:

 # include<stdio.h>
# include<string.h>
const int MAXN = <<;
const int MOD = ;
int sta[MAXN],num;
int dp[][MAXN]; //dp[i][j]表示第i行在集合j中满足条件的方案数
int map[]; //表示输入中每一行的状态
int n,m;
void init(){
num =;
int sum = <<m;
for(int i=; i<sum;i++) //从1到sum里边有满足该状态中放牛的位置不相邻的方案有num个
if(i&(i<<))
continue;
else
sta[num++] = i;
} void DP(){
int i,j,k;
memset(dp,,sizeof(dp));
for(i=; i<num; i++)
if(!(sta[i]&map[])) //寻找第一层满足条件的方案,令它为1
dp[][i] = ;
for(i=; i<n; i++){
for(j=; j<num; j++) { //第i行是状态j
dp[i%][j] = ; //用来初始化,在滚动数组里边很重要
if(sta[j]&map[i]) //去掉与草场矛盾
continue;
else
for(k=; k<num; k++){ //第i-1行是状态k
if(map[i-]&sta[k]) //去掉与草场矛盾的
continue;
if(sta[k]&sta[j]) //去掉与上一行状态矛盾的
continue;
dp[i%][j] = (dp[i%][j] + dp[(i+)%][k]) % MOD;
}
}
}
int ans = ;
int temp = (n+)%;
for(i=; i<num; i++)
ans = (ans+dp[temp][i])%MOD;
printf("%d\n",ans);
}
int main(){
int i,j,temp;
while(scanf("%d%d",&n,&m)!=EOF){
memset(map,,sizeof(map));
for(i=; i<n; i++)
for(j=; j<m; j++){
scanf("%d",&temp);
if(temp==) //将每行状态二进制表示,1代表题目中的0,代表1
map[i] += <<(m-j-);
}
init();
DP();
}
return ;
}

POJ 3254 Corn Fields(DP + 状态压缩)的更多相关文章

  1. poj - 3254 - Corn Fields (状态压缩)

    poj - 3254 - Corn Fields (状态压缩)超详细 参考了 @外出散步 的博客,在此基础上增加了说明 题意: 农夫有一块地,被划分为m行n列大小相等的格子,其中一些格子是可以放牧的( ...

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

    一道状态压缩的题,错了好多次....应该先把满足的情况预处理出来 #include<iostream> #include<cstdio> #include<cstring ...

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

    题目大意:给出一个M*N的矩阵,元素为0表示这个地方不能种玉米,为1表示这个地方能种玉米,现在规定所种的玉米不能相邻,即每行或者没列不能有相邻的玉米,问一共有多少种种植方法. 举个例子: 2 3 1 ...

  4. POJ 3254 Corn Fields [DP]

    题意:略. 思路:第一次做状态压缩的dp. 在这里说一下状态压缩的原则.因为每一行只有最多12个格子,每个格子只有1(可放牛)和0(不可放牛)两种状态,这总共是2^12种状态,直接用一个int整型变量 ...

  5. 状压DP POJ 3254 Corn Fields

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

  6. poj3254 Corn Fields 利用状态压缩求方案数;

    Corn Fields 2015-11-25 13:42:33 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10658   ...

  7. poj 3254 Corn Fields

    http://poj.org/problem?id=3254 Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissio ...

  8. POJ 3254. Corn Fields 状态压缩DP (入门级)

    Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9806   Accepted: 5185 Descr ...

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

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

  10. POJ 3254 Corn Fields 状态压缩DP (C++/Java)

    id=3254">http://poj.org/problem? id=3254 题目大意: 一个农民有n行m列的地方,每一个格子用1代表能够种草地,而0不能够.放牛仅仅能在有草地的. ...

随机推荐

  1. c++面试常见160问

    1.在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern "C"?答:首先,extern是C/C++语言中表明函数和全局变量作用范围的关键字,该关键字告诉编译器,其 ...

  2. 小波变换和motion信号处理(一)(转)

    写的太好,不得不转:http://www.kunli.info/2011/02/15/fourier-wavelet-motion-signal-1/ 这是<小波变换和motion信号处理> ...

  3. 编译android版libmpg

    环境:ubutnu 12.04,android SDK 1. 下载libmpg的一个android工程,得到一个Android-libmpg-master.zip.https://github.com ...

  4. cep

  5. 高效Linux用户需要了解的命令行技能

    最近在Quora上看到一个问答题目,关于在高效率Linux用户节省时间Tips. 将该题目的回答进行学习总结,加上自己的一些经验,记录如下,方便自己和大家参考. 下面介绍的都是一些命令行工具,这些工具 ...

  6. 巧用MySQL之Explain进行数据库优化

    前记:很多东西看似简单,那是因为你并未真正了解它. Explain命令用于查看执行效果.虽然这个命令只能搭配select类型语句使用,如果你想查看update,delete类型语句中的索引效果,也不是 ...

  7. Jquery常用方法篇(一)

    1.add方法:将匹配的元素添加到当前的jquery对象集合中. 语法 add(expr,[context]) 参数1表示 用于匹配元素选择器(待添加的对象),或者用于动态生成的HTML代码(字符串) ...

  8. JS好的学习网站

    1.JavaScript 秘密花园 2.W3CSchool 3.js严格模式 4.js核心之原型 5.尼古拉斯怎么面试前端工程师 6.zepto中文版api 7.jquery API

  9. MSSQLSERVER数据库- 杂记

    查看语句执行时间: SET STATISTICS IO ONSET STATISTICS TIME ON SELECT * FROM dbo.NewsInfo Update的表关联例子: UPDATE ...

  10. [HTTP] HTTP Verb

    HEAD: HEAD / HTTP/1.1 nc.exmaple.com HEAD is a interesting method, it allow you to get a header of f ...