POJ 1684 Corn Fields(状压dp)

描述

Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and can‘t be planted. Canny FJ knows that the cows dislike eating close to each other, so when choosing which squares to plant, he avoids choosing squares that are adjacent; no two chosen squares share an edge. He has not yet made the final choice as to which squares to plant.

Being a very open-minded man, Farmer John wants to consider all possible options for how to choose the squares for planting. He is so open-minded that he considers choosing no squares as a valid option! Please help Farmer John determine the number of ways he can choose the squares to plant.

输入

Line 1: Two space-separated integers: M and N
Lines 2..M+1: Line i+1 describes row i of the pasture with N space-separated integers indicating whether a square is fertile (1 for fertile, 0 for infertile)

输出

Line 1: One integer: the number of ways that FJ can choose the squares modulo 100,000,000.

样例输入

2 3

1 1 1

0 1 0

样例输出

9

提示

Number the squares as follows:

1 2 3  4  

There are four ways to plant only on one squares (1, 2, 3, or 4), three ways to plant on two squares (13, 14, or 34), 1 way to plant on three squares (134), and one way to plant on no squares. 4+3+1+1=9.

题意

一块M*N的田用于养牛,1代表可以养牛,要求每头牛上下左右没有其他牛,问你方案数模1e9

题解

状压dp经典题,这里用样例解释

首先把列压成01串状态,1表示有牛,0表示无牛,那么总共有[000,111]总状态,000,001,010,011,100,101,110,111

dp[i][j]代表第i行可行状态j的方案总数,可行状态j的意思是没有两个连续的1,所以011和110和111去掉

state[i]代表可行的状态,所以只有000,001,010,100,101五种状态,此时所有可行状态数tot=5

cur[i]代表样例行的状态取反,取反是为了判断当前行枚举的五种状态是否可行,例如第二行题目是010,取反后是101,也就是说只有000,010两种状态可行

状态转移方程

if      j∈[1,tot],state[j]&cur[i]=0,k∈[1,tot],state[k]&cur[i-1]=0,state[j]&state[k]=0

dp[i][j]=dp[i][j]+dp[i-1][k]表示当前行i状态j可由前一行i-1状态k转移过来

else

dp[i][j]=dp[i][j];

代码

 1 #include<stdio.h>
 2 #include<string.h>
 3 using namespace std;
 4
 5 const int mod=1e9;
 6
 7 int dp[15][1500],state[1500],cur[15];
 8 int n,m,k,tot;
 9 int main()
10 {
11     while(scanf("%d%d",&m,&n)!=EOF)
12     {
13         tot=0;
14         for(int i=0;i<(1<<n);i++)///列的所有可行状态
15             if(!(i&(i<<1)))///没有连续两个1
16                 state[++tot]=i;
17
18         for(int i=1;i<=m;i++)
19             for(int j=1;j<=n;j++)
20             {
21                 scanf("%d",&k);
22                 if(!k)cur[i]+=1<<(n-j);///第i行不可行置1,用于判断不可行状态
23             }
24
25         for(int i=1;i<=tot;i++)
26             if(!(state[i]&cur[1]))
27                 dp[1][i]=1;
28         for(int i=2;i<=m;i++)
29         {
30             for(int j=1;j<=tot;j++)///枚举当前状态
31             {
32                 if(state[j]&cur[i])continue;///当前状态不可行
33                 for(int k=1;k<=tot;k++)///枚举前一个状态
34                 {
35                     if(state[k]&cur[i-1])continue;///当前前一状态不可行
36                     if(state[j]&state[k])continue;///当前状态和前一状态不可行
37                     dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;///当前状态可以从前一状态的K状态转移过来
38                 }
39             }
40         }
41         int ans=0;
42         for(int i=1;i<=tot;i++)
43             ans=(ans+dp[m][i])%mod;
44         printf("%d\n",ans);
45     }
46     return 0;
47 }

原文地址:https://www.cnblogs.com/taozi1115402474/p/9315727.html

时间: 2024-10-03 11:08:07

POJ 1684 Corn Fields(状压dp)的相关文章

POJ 3254 Corn Fields 状压DP

链接:http://poj.org/problem?id=3254 题意:一块M*N的田地,每小块地大小是1*1,可以种植物的标记为1,不可以种植物的标记为0,并且相邻的两块地不可以同时种植物.问题是有多少种不同的种植方案(所有地都不种也是一种种植方案) 思路:这是第一道状压DP题,从第一行更新到最后一行,每一行用一个N位的二进制数来表示该行的状态1表示该位置种了植物,0表示该位置没种植物.因为每块地只对相邻的土地能否种植有所影响,所以每一行的状态可以用前一行的状态递推得到. 资料:http:/

poj 3254 Corn Fields 状压dp入门

// poj3254 状压dp入门 // dp[i][S]表示前i行第i行状态为S时放牧的情况 // S为十进制的二进制数形式如5为101表示第一列和第三列放牧的方法数 // 首先dp[0][S]合法的话就是1 // 状态转移方程为dp[i][S] = sigma(dp[i-1][V])(S与V是合法状态) // 最后的结果就是dp[n][S](S为所有的合法状态) // // 刚开始十分傻x的dp[0][S]置为get(S),...get(S)是其中1的个数 // 这又不是求放羊的数量,这是方

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

题意: 有一块n*m的土地 0代表不肥沃不可以放牛 1代表肥沃可以放牛 且相邻的草地不能同时放牛 问最多有多少种放牛的方法并对1e8取模 思路: 典型的状压dp 能状态压缩 能状态转移 能状态压缩的题的特点就是只有两种状态 所以用0 1表示两种状态 用位运算判断是否符合条件 然后将前一行的合理状态转移到后一行 最后统计最后一行的状态 dp[i][j]代表第i行以第j种状态放牛时有多少种不同的状态 (c++的语言特性是 封装 继承 多态~) 1 /* ***********************

POJ 3254 Corn Fields (状压DP+滚动数组)

题目地址:POJ 3254 状压水题. 先预处理出每行所有可能出现的情况.然后可以用vector存起来. 然后先处理出第一行所有的情况.然后再从第二行开始不断与上一行进行状态转移,状态转移很简单就不说了. 最后统计出最后一行的个数和就可以了. 代码如下; #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #

题解——[USACO06NOV]玉米田Corn Fields 状压DP

题面: 农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地.John打算在牧场上的某几格里种上美味的草,供他的奶牛们享用. 遗憾的是,有些土地相当贫瘠,不能用来种草.并且,奶牛们喜欢独占一块草地的感觉,于是John不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边. John想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择?(当然,把新牧场完全荒废也是一种方案) 输出一个整数,即牧

P1879 [USACO06NOV]玉米田Corn Fields 状压dp

链接在此! 正解:状压dp(emm……据说插头dp也可以趴但我不管!!!不会!!! 解题报告: ……我真的太菜了……我以为一个小时前要搞完的题目调错误调了一个小时……90分到100我差不多搞了一个小时…… 然后这题还是做过的……就很气,觉得确实是要搞下博客没事儿复习下不然做过的题目还花俩小时我真的哭死…… 先放上错误的90分代码讲一下错哪儿了(因为……其实100并不难是可以想到的……没有太大讲的意义,主要我太菜了所以才会搞这么久TT 点我♂看♂沙雕灵巧在线WA题 然后错误的点是最后一个点RE,开

[USACO06NOV]玉米田Corn Fields (状压$dp$)

题目链接 Solution 状压 \(dp\) . \(f[i][j][k]\) 代表前 \(i\) 列中 , 已经安置 \(j\) 块草皮,且最后一位状态为 \(k\) . 同时多记录一个每一列中的不能放的位置 \(w[i]\). 然后就可以很轻松的转移了... 转移方程看代码. Code #include<bits/stdc++.h> #define ll long long using namespace std; ll f[13][145][10000],n,K; ll js[1000

TOJ 2850 Corn Fields 状压dp

Source: http://acm.tju.edu.cn/toj/showp.php?pid=2850 题意:n*m的土地上种东西,每个位置分为可以种和不能,种的方案要求不能相邻地种,问合法方案数.(写得有点乱) 分析:做过炮兵阵地,这题就是秒杀了. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int mo = 1000000

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

http://poj.org/problem?id=3254 题目大意: 一个农民有n行m列的地方,每个格子用1代表可以种草地,而0不可以.放牛只能在有草地的,但是相邻的草地不能同时放牛, 问总共有多少种方法. 思路: 状态压缩的DP. 可以用二进制数字来表示放牧情况并判断该状态是否满足条件. 这题的限制条件有两个: 1.草地限制. 2.相邻限制. 对于草地限制,因为输入的时候1是可以种草地的. 以"11110"草地分析,就只有最后一个是不可以种草的.取反后得00001  .(为啥取反