题目链接: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. CosCos2D-android 代码总结

    CosCos2D-android 学习总结 资料: Android游戏开发视频教程 Cocos-android-1代码包下载 直接上代码: MainActivity中Cocos常规写法: //coco ...

  2. leetcode—triangle

    1.题目描述 Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adj ...

  3. 泰泽新闻:英特尔三星双否认泰泽Tizen系统已死

    7月8日 据媒体TizenExperts报道,关于“Tizen系统跳票”的传闻已经遭到了英特尔和三星否认. 此前传闻三星自行研制的智能手机Tizen操作系统流产,但如今已经遭到了官方的否认. 英特尔三 ...

  4. 【Java基础】Java异常的一些总结

    什么是异常 异常是指程序运行可能出现的不能正常继续的情况,也可以理解为程序出现了不在预期范围内的一些情况,都可以称之为异常. 异常的分类 所有的异常类是从java.lang.Exception类继承的 ...

  5. HW4.38

    import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...

  6. Java条形码生成方案及二维码要点

    1.什么是条形码及其应用 条形码(barcode)是将宽度不等的多个黑条和空白,按照一定的规则排列,用来表示一组信息的图形标识符.常见的条形码是由反射率相差很大的黑条和白条排成的平行线图案. 条形码可 ...

  7. 如何用Windbg找到被catch住的C++的异常

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:如何用Windbg找到被catch住的C++的异常.

  8. SAP生产订单状态

    SAP系统的常见订单状态如下: ·        CRTD (创建):标识生产订单刚刚创建,此时禁止做后续发料和报工确认等操作: ·        PREL (部分下达):当生产订单部分下达时,如仅下 ...

  9. IIS7错误:“Web服务器被配置为不列出此目录的内容”的解决办法

    IIS7错误:“Web服务器被配置为不列出此目录的内容”的解决方法: 在"操作"下,点启用,此按钮将变成禁用,则可消除此错误

  10. VM启用ISO共享

    在SCVMM中可以启用ISO共享,如下图: 如果不勾选共享镜像复选框,则vmm会把镜像文件通过网络复制到Hyper-v主机下的虚拟机配置文件夹中 配置步骤如下: 1.新建一个共享文件夹(存放ISO), ...