bzoj 1725 Corn Fields
阿新 • • 發佈:2018-11-22
Written with StackEdit.
Description
Farmer John新買了一塊長方形的牧場,這塊牧場被劃分成M列N行\((1<=M<=12; 1<=N<=12)\),每一格都是一塊正方形的土地。FJ打算在牧場上的某幾格土地裡種上美味的草,供他的奶牛們享用。遺憾的是,有些土地相當的貧瘠,不能用來放牧。並且,奶牛們喜歡獨佔一塊草地的感覺,於是FJ不會選擇兩塊相鄰的土地,也就是說,沒有哪兩塊草地有公共邊。當然,FJ還沒有決定在哪些土地上種草。 作為一個好奇的農場主,FJ想知道,如果不考慮草地的總塊數,那麼,一共有多少種種植方案可供他選擇。當然,把新的牧場荒廢,不在任何土地上種草,也算一種方案。請你幫FJ算一下這個總方案數。
Input
- 第1行: 兩個正整數\(M\)和\(N\),用空格隔開
第\(2..M+1\)行: 每行包含\(N\)個用空格隔開的整數,描述了每塊土地的狀態。輸入的第\(i+1\)行描述了第i行的土地。所有整數均為\(0\)或\(1\),是\(1\)的話,表示這塊土地足夠肥沃,\(0\)則表示這塊地上不適合種草.
Output
第\(1\)行: 輸出一個整數,即牧場分配總方案數除以\(100000000\)的餘數
Sample Input
2 3
1 1 1
0 1 0Sample Output
9
Solution
- 狀壓\(dp\)的入門題.
- 注意每一行有共同的限制,即不能有相鄰的.可以預處理此條件下合法的方案,轉移時再加上其他限制即可.
可以滾成一維,但沒必要.
#include<bits/stdc++.h> using namespace std; typedef long long LoveLive; inline int read() { int out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') { fh=-1; jp=getchar(); } while (jp>='0'&&jp<='9') { out=out*10+jp-'0'; jp=getchar(); } return out*fh; } const int P=1e8; inline int add(int a,int b) { return (a + b) % P; } inline int mul(int a,int b) { return 1LL * a * b % P; } const int MAXN=13; const int MAXS=1<<13; int n,m; int fix[MAXN][MAXN]; int f[MAXN][MAXS]; int g[MAXS],tot=0; vector<int> G[MAXN]; inline int judge(int st) { int ls=0; while(st) { int p=st&1; if(p && ls) return 0; ls=p; st>>=1; } return 1; } int check(int cur,int r) { int cnt=1; while(cur) { int p=cur&1; if(p && fix[r][cnt]==0) return 0; ++cnt; cur>>=1; } return 1; } int main() { n=read(),m=read(); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) fix[i][j]=read(); int S=1<<m; for(int i=0;i<S;++i) if(judge(i)) g[++tot]=i; G[0].push_back(0); f[0][0]=1; int ans=0; for(int i=1;i<=n;++i) { int sizls=G[i-1].size(); for(int p=1;p<=tot;++p) { int st=g[p]; if(check(st,i)) { G[i].push_back(st); for(int j=0;j<sizls;++j) { int k=G[i-1][j]; if(!(st&k)) f[i][st]=add(f[i][st],f[i-1][k]); } } if(i==n) ans=add(ans,f[i][st]); } } printf("%d\n",ans); return 0; }