您的位置:首页 > 其它

POJ3254 Corn Fields(状态DP)

2014-03-11 20:35 218 查看
【POJ3254】Corn Fields

【题目大意】一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求
(1)两个相邻的方格不能同时放牛,即牛与牛不能相邻。问有多少种放牛方案(一头牛都不放也是一种方案)

【解析】根据题意,把每一行的状态用二进制的数表示,0代表不在这块放牛,1表示在这一块放牛。

const int Max_N = 4100 ;
const int Mod = 100000000 ;
int N , M ;
int dp[13][Max_N] ;/*截止到(第i行,状态为j)的中情况数*/
int cannot[13] ; //第i行已经不能放的初始情况
/*判断状态i是否满足左右不相邻*/
int ok(int x){
if(x & (x<<1))
return 0 ;
if(x & (x>>1))
return 0 ;
return 1 ;
}

void get_all_states(vector<int> &states){
states.clear() ;
for(int i = 0 ; i < (1<<M) ; i++){
if(ok(i))
states.push_back(i) ;
}
}

int DP(){
int i , j , row ;
vector<int> state ;
get_all_states(state) ;
memset(dp , 0 , sizeof(dp)) ;
for(i = 0 ; i < state.size() ; i++){
if(state[i] & cannot[1])
continue ;
dp[1][state[i]] = 1 ;
}
for(row = 2 ; row <= N ; row++){
for(i = 0 ; i < state.size() ; i++){
if(state[i] & cannot[row])
continue ;
for(j = 0 ; j < state.size() ; j++){
if(state[j] & cannot[row-1])
continue ;
if(state[i] & state[j]) //上下不相邻
continue ;
dp[row][state[i]] += dp[row-1][state[j]] ;
dp[row][state[i]] %= Mod ;
}
}
}
int ans = 0 ;
for(i = 0 ; i < state.size() ; i++)
ans = (ans + dp
[state[i]] ) % Mod ;
return ans ;
}

int main(){
int x ;
while(cin>>N>>M){
for(int i = 1 ; i <= N ; i++){
cannot[i] = 0 ;
for(int j = 1 ; j <= M ; j++){
cin>>x ;
if(x == 0)
cannot[i] |= (1<<(M-j)) ;
}
}
cout<<DP()<<endl ;
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: