您的位置:首页 > 其它

POJ 3254 Corn Fields

2013-11-23 00:22 375 查看
题意:在m*n的矩阵上,1表示能放牛,0表示不能放。要求放的牛不能相邻(上下相邻或者左右相领),问放牛的方法种数。

解法:设d[i][j]表示第i行状态为j的情况下,能放的牛的数量。d[i][j] += d[i-1][k],其中k表示能转移到j的状态,num(j)表示状态为j的行所放的牛的数量。当然,还要判断一下状态j是不是能放在第i行。

tag:状压dp

/*
* Author:  Plumrain
* Created Time:  2013-11-18 23:37
* File Name: DP-POJ-3254.cpp
*/
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

#define CLR(x) memset(x, 0, sizeof(x))
const int mod = 100000000;

int n, m, a[20][20];
int d[20][1<<13];

void init()
{
for (int i = 0; i < n; ++ i)
for (int j = 0; j < m; ++ j)
scanf ("%d", &a[i][j]);
}

bool gao1(int sta)
{
int x = 0;
while (sta > 0){
if (x == 1 && (sta&1))
return 0;
x = sta & 1;
sta >>= 1;
}
return 1;
}

bool gao2(int sta, int k)
{
for (int i = 0; i < m; ++ i)
if (!a[k][i] && (sta & (1<<i))) return 0;
return 1;
}

bool gao3(int s1, int s2)
{
for (int i = 0; i < (1<<m); ++ i){
int t1 = s1 & (1<<i), t2 = s2 & (1<<i);
if (t1 && t2) return 0;
}
return 1;
}

int DP()
{
CLR (d);
for (int i = 0; i < (1<<m); ++ i)
if (gao1(i) && gao2(i, 0)) d[0][i] = 1;

for (int i = 1; i < n; ++ i)
for (int j = 0; j < (1<<m); ++ j){
d[i][j] = 0;
if (gao1(j) && gao2(j, i))
for (int k = 0; k < (1<<m); ++ k)
if (gao3(j, k)) d[i][j] = (d[i][j] + d[i-1][k]) % mod;
}

int ret = 0;
for (int i = 0; i < (1<<m); ++ i)
if (gao1(i) && gao2(i, n-1)) ret = (d[n-1][i] + ret) % mod;
return (int)ret;
}

int main()
{
while (scanf ("%d%d", &n, &m) != EOF){
init();
printf ("%d\n", DP());
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: