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

http://poj.org/problem?id=3254

参考:http://blog.csdn.net/accry/article/details/6607703

农夫想在m*n的土地上种玉米,但是有的土地很贫瘠,所以不能种,每块土地标为1的表示能种,标为0的表示不能种,并且种玉米的土地不能相邻,

问有多少种合法的种植方案.(全部不种也算一种)

第一道状压,理解了比较久的时间.

就是用二进制的0和1代表土地种还是不种,这样每一行都可以用一个2进制数表示,列数<=12,故最多有2<<12种状态.

代表一个状态,就可以建立状态转移方程.dp[i][j]代表第i行状态为j时总的方案数,dp[i][j]=sigma(dp[i-1][j‘]);

判断冲突充分利用了位运算的性质,比如某个状态是否有相邻的1存在则状态x&(x>>1) 或者x&(x<<1)即可.因为等于向左或向右移动一位.

判断是否跟上一行的冲突也是一样.

用滚动数组总是写的不对,好像是初始化的问题.

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cmath>
  4 #include <vector>
  5 #include <cstring>
  6 #include <string>
  7 #include <algorithm>
  8 #include <string>
  9 #include <set>
 10 #include <functional>
 11 #include <numeric>
 12 #include <sstream>
 13 #include <stack>
 14 //#include <map>
 15 #include <queue>
 16 #include <deque>
 17 //#pragma comment(linker, "/STACK:102400000,102400000")
 18 #define CL(arr, val)    memset(arr, val, sizeof(arr))
 19
 20 #define ll long long
 21 #define INF 0x7f7f7f7f
 22 #define lc l,m,rt<<1
 23 #define rc m + 1,r,rt<<1|1
 24 #define pi acos(-1.0)
 25
 26 #define L(x)    (x) << 1
 27 #define R(x)    (x) << 1 | 1
 28 #define MID(l, r)   (l + r) >> 1
 29 #define Min(x, y)   (x) < (y) ? (x) : (y)
 30 #define Max(x, y)   (x) < (y) ? (y) : (x)
 31 #define E(x)        (1 << (x))
 32 #define iabs(x)     (x) < 0 ? -(x) : (x)
 33 #define OUT(x)  printf("%I64d\n", x)
 34 #define lowbit(x)   (x)&(-x)
 35 #define Read()  freopen("a.txt", "r", stdin)
 36 #define Write() freopen("b.txt", "w", stdout);
 37 #define maxn 110
 38 #define maxv 5010
 39 #define mod 1000000000
 40 using namespace std;
 41 int n,m,top=0;
 42 int state[600],num[110];
 43 int dp[20][600]; //最多是600个状态,不知道是以什么方式算出来的
 44 int cur[20];
 45 inline bool ok(int x) //判断同一行是否有相邻的1
 46 {
 47     if(x&x<<1) return 0;
 48     return 1;
 49 }
 50 void init() //初始化 2^m个状态,把有相邻1的状态的去掉
 51 {
 52     top=0;
 53     int total=1<<m;
 54     for(int i=0;i<total;i++)
 55         if(ok(i)) state[++top]=i;
 56 }
 57 inline bool fit(int x,int k) //判断状态x和读入的第k行是否冲突,注意cur[k]中1代表不能种,
 58 {                            //所以只要相与为1则表示不行
 59     if(x&cur[k]) return 0;
 60     return 1;
 61 }
 62 int main()
 63 {
 64     //Read();
 65     while(~scanf("%d%d",&n,&m))
 66     {
 67         init();
 68         memset(dp,0,sizeof(dp));
 69         for(int i=1;i<=n;i++)
 70         {
 71             cur[i]=0;
 72             int num;
 73             for(int j=1;j<=m;j++) //这里是为0表示可以种,为1表示是不可以种
 74             {                     //注意和上面区分,这里主要是为了判断冲突.
 75                 scanf("%d",&num);
 76                 if(!num) cur[i]+=(1<<(m-j));//把每一行转换成2进制,并用cur存储
 77             }
 78             //printf("%d\n",cur[i]);
 79         }
 80         for(int i=1;i<=top;i++) //初始化第一行,
 81         {
 82             if(fit(state[i],1)) //不冲突表示可以放
 83                 dp[1][i]=1;
 84         }
 85         for(int i=2;i<=n;i++)
 86         {
 87             for(int j=1;j<=top;j++)
 88             {
 89                 if(!fit(state[j],i)) continue; //判断第i行和读入的图是否冲突
 90                 for(int k=1;k<=top;k++)
 91                 {
 92                     if(!fit(state[k],i-1)) continue; //判断第i-1行是否冲突
 93                     if(state[j]&state[k]) continue;//判断第i行和第i-1行是否冲突
 94                     dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;
 95                 }
 96             }
 97         }
 98         int ans=0;
 99         for(int i=1;i<=top;i++)
100         {
101             ans=(ans+dp[n][i])%mod;
102         }
103         printf("%d\n",ans);
104     }
105     return 0;
106 }
时间: 2024-10-13 11:59:34

poj - 3254 Corn Fields (状态压缩入门)的相关文章

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

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

POJ 3254 Corn Fields 状态压缩DP

题目链接:http://poj.org/problem?id=3254 思路:状态压缩DP,状态方程为dp[i][j] += (dp[i-1][k]) code: #include <stdio.h> #include <string.h> #define N 500 const int MOD = 100000000; int dp[15][N],ant[N],n,m,k,map[15]; bool ok(int x) { if(x&(x<<1))return

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

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9806   Accepted: 5185 Description 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 yumm

POJ 3254 Corn Fields(状态压缩DP)

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4739   Accepted: 2506 Description 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 yumm

[ACM] POJ 3254 Corn Fields(状态压缩)

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8062   Accepted: 4295 Description 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 yumm

Poj 3254 Corn Fields(状态压缩)

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8291   Accepted: 4409 Description 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 yumm

poj 3254 Corn Fields 国家压缩dp

意甲冠军: 要在m行n陆行,有一些格您可以种树,别人做不到的.不相邻的树,我问了一些不同的共同拥有的法律. 分析: 从后往前种,子问题向父问题扩展,当种到某一格时仅仅有他和他后面的n-1个格子的情况对它有影响.故对这n个格子进行编码为状态S,表示种完(多米诺骨牌那题是放置前.注意差别,都可行)这n个格子的状态.父问题由稍小子问题逐步解决,正是动态规划的思想. 代码: //poj 3254 //sep9 #include <iostream> using namespace std; const

POJ 3254 Corn Field ( 状态压缩DP )

简单题,边界处理注意.可以优化,就不精益求精了. #include <iostream> #include <cstring> #include <vector> #include <fstream> using namespace std; #define MOD 100000000 int field[20]; int DP[20][1200]; int main(){ int N, M; cin >> N >> M; memse

poj 3254 Corn Fields ,状态压缩DP

题目链接 题意: 一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻.问有多少种放牛方案(一头牛都不放也是一种方案) state[i] 表示对于一行,保证不相邻的方案 状态:dp[i][ state[j] ]  在状态为state[j]时,到第i行符合条件的可以放牛的方案数 状态转移:dp[i][ state[j] ] =Sigma dp[i-1][state'] (state'为符合条