日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2024/6/21 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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入门)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。