题目链接:POJ 3254 Corn Fields
状态压缩dp。
state存储每一行可能的状态,limit存储某一行的限制的相反。注意&运算和两个数组的关系。
状态转移方程:dp[i][j]=sum{dp[i-1][k]}(其中k为上一行的合法方案,并且不合方案j冲突)。
状压dp好神奇。。
#include <iostream>
#include <cstring>
using namespace std;
const int MOD = 100000000;
const int MAX_N = 12 + 3;
const int MAX_M = 1 << MAX_N;
int n, m, cnt, dp[MAX_N][MAX_M], state[MAX_M], limit[MAX_M];
bool ok(int x)
{
if(x & (x << 1))
return false;
return true;
}
void getState(int n)
{
for(int i = 0;i < (1 << n);i++)
{
if(ok(i))
state[cnt++] = i;
}
}
int main()
{
memset(dp,0,sizeof(dp));
cin >> n >> m;
getState(m);
int temp;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
cin >> temp;
if(temp == 0)
limit[i] |= (1 << j);
}
}
for(int i = 0; i < cnt; i++)
if(!(limit[0] & state[i]))
dp[0][i] = 1;
for(int i = 1; i < n; i++)
{
for(int j = 0; j < cnt;j++)
{
if(limit[i] & state[j])
continue;
for(int k = 0; k < cnt;k++)
{
if(limit[i - 1] & state[k] || state[j] & state[k])
continue;
dp[i][j] = (dp[i][j] + dp[i - 1][k]) % MOD;
}
}
}
int ans = 0;
for(int i = 0; i < cnt; i++)
ans = (ans + dp[n - 1][i]) % MOD;
cout << ans << endl;
return 0;
}