「USACO06NOV」玉米田 Corn Fields
解题思路
这题是一道经典的状压(DP)
设 (f_{i,j}) 表示当前处理到第 (i) 行,这行的状态为 (j) 。
转移更简单
[f_{i,j} = sum _ {k = 1} ^ {k <= w} f _ {i - 1,k}
]
(w) 为 (i - 1) 行的状态数量
转移时要排除不可能的情况
对于状态,我们可以用 预处理出每一行有可能的状态
时间复杂度为(O(2 ^ {2m} n)),不会跑满
Code
#include<cstdio>
using namespace std;
const int P = 1e8;
long long f[14][4400];
int sta[14][4400],n,m,a[14][14];
void dfs(int u,int x,int s)\预处理状态
{
if (x > m)
{
sta[u][++sta[u][0]] = s;
return;
}
dfs(u,x + 1,s);
if (a[u][x]) dfs(u,x + 2,s | (1 << x - 1));
}
int main()
{
freopen("cowfood.in","r",stdin);
freopen("cowfood.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d",&a[i][j]);
for (int i = 1; i <= n; i++)
dfs(i,1,0);
for (int i = 1; i <= sta[1][0]; i++) f[1][i] = 1;
for (int i = 2; i <= n; i++)
for (int j = 1; j <= sta[i][0]; j++)
for (int k = 1; k <= sta[i - 1][0]; k++)
{
if (sta[i][j] & sta[i - 1][k]) continue;\排除不可能的情况
f[i][j] = (f[i][j] + f[i - 1][k]) % P;
}
long long ans = 0;
for (int i = 1; i <= sta[n][0]; i++) ans = (ans + f[n][i]) % P;
printf("%lld
",ans);
}