bzoj1725: [Usaco2006 Nov]Corn Fields牧場的安排(狀壓dfs)
阿新 • • 發佈:2018-11-08
1725: [Usaco2006 Nov]Corn Fields牧場的安排
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 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 31 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
/*
我才不要寫狀壓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;
}