1. 程式人生 > >bzoj1725: [Usaco2006 Nov]Corn Fields牧場的安排(狀壓dfs)

bzoj1725: [Usaco2006 Nov]Corn Fields牧場的安排(狀壓dfs)

1725: [Usaco2006 Nov]Corn Fields牧場的安排

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 1122  Solved: 807
[Submit][Status][Discuss]

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行: 輸出一個整數,即牧場分配總方案數除以100,000,000的餘數

Sample Input

2 3
1 1 1
0 1 0


Sample Output

9

輸出說明:

按下圖把各塊土地編號:

1 2 3
4

只開闢一塊草地的話,有4種方案:選1、2、3、4中的任一塊。開闢兩塊草地的話,有3種方案:13、14以及34。選三塊草地只有一種方案:134。再加把牧場荒廢的那一種,總方案數為4+3+1+1=9種。

HINT

 

Source

Gold

 

/*
我才不要寫狀壓dp呢!! 
狀壓dfs
對於每一行dfs一次。順便記錄這一行的狀態能否對下一行的狀態產生貢獻。
*/
#include<bits/stdc++.h>

#define N 100000
#define S 30
#define mod 100000000

using namespace std;
int m,n,ans;
int f[S][N],a[S];

inline int read()
{
    int x=0,f=1;char c=getchar();
    
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } void dfs(int x,int y,int sta,int nxt)//nxt是下行狀態 { if(y>=n) { f[x+1][nxt]+=f[x][sta]; f[x+1][nxt]%=mod; return; } dfs(x,y+1,sta,nxt);//不放 if(!(sta&(1<<y))) dfs(x,y+2,sta,nxt|(1<<y));//保證左右,和下面不相鄰 } int main() { int x; m=read();n=read(); for(int i=1;i<=m;i++) for(int j=0;j<n;j++) { x=read(); if(x==0) a[i]=a[i]|(1<<j); }f[1][a[1]]=1;//初始,第一行,不放,方案數為1 for(int i=1;i<=m;i++) for(int j=a[i];j<(1<<n);j++) if(f[i][j]) dfs(i,0,j,a[i+1]);//如果當前航這個狀態合法,就從這個狀態dfs for(int i=0;i<(1<<n);i++) ans+=f[m+1][i],ans%=mod; printf("%d\n",ans); return 0; }