POJ-325Corn Fields

链接:https://vjudge.net/problem/POJ-3254#author=freeloop

题意:

农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地。John打算在牧场上的某几格里种上美味的草,供他的奶牛们享用。

遗憾的是,有些土地相当贫瘠,不能用来种草。并且,奶牛们喜欢独占一块草地的感觉,于是John不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。

John想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择?(当然,把新牧场完全荒废也是一种方案)

思路:

状压dp,二进制表示每一行的状态,储存时使用十进制。

具体思路注释。

代码:

#include <iostream>
#include <memory.h>
#include <string>
#include <istream>
#include <sstream>
#include <vector>
#include <stack>
#include <algorithm>
#include <map>
#include <queue>
#include <math.h>
#include <cstdio>
using namespace std;

typedef long long LL;
const int MAXN = 15;
const int STATES = 600;
const int MOD = 1e9;

//377 最多状态

int cur[MAXN];
int dp[MAXN][STATES];
int states[STATES];
int pos = 0;

void Init(int w)
{
    int total = (1 << w);
    for (int i = 0;i < total;i++)
    {
        if(!(i&(i<<1)))//i往左位移以为,是否有两个1重叠,重叠不满足
            states[++pos] = i;
    }
}

int main()
{
    int n, m;
    int flag;
    scanf("%d%d", &m, &n);
    Init(n);
    for (int i = 1;i <= m;i++)
        for (int j = 1;j <= n;j++)
        {
            scanf("%d", &flag);
            if (!flag)//方便判断某种状态是否满足,0时加
                cur[i] += (1 << (n - j));
        }

    for (int i = 1;i <= pos;i++)
    {
        if ((cur[1] & states[i]) == 0)//状态为1表示种,同时行状态为1表示不能种
            dp[1][i] = 1;
    }

    for (int i = 2;i <= m;i++)
    {
        for (int j = 1;j <= pos;j++)
        {
            if (states[j] & cur[i])//枚举的状态是否冲突当前行
                continue;
            for (int k = 1;k <= pos;k++)
            {
                if (states[k] & cur[i - 1])//枚举的上一行状态是否冲突
                    continue;
                if (states[j] & states[k])//枚举的上下两行状态是否冲突
                    continue;
                dp[i][j] = (dp[i][j] + dp[i - 1][k]) % MOD;
            }
        }
    }

    int res = 0;
    for (int i = 1;i <= pos;i++)
        res = (res + dp[m][i]) % MOD;

    printf("%d\n", res);

    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/YDDDD/p/10359877.html