poj - 3254 Corn Fields (状态压缩dp入门)
生活随笔
收集整理的這篇文章主要介紹了
poj - 3254 Corn Fields (状态压缩dp入门)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
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 }?
轉載于:https://www.cnblogs.com/nowandforever/p/4713997.html
總結
以上是生活随笔為你收集整理的poj - 3254 Corn Fields (状态压缩dp入门)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaScript学习笔记——BOM_
- 下一篇: BNU 26349——Cards————