POJ 3254 Corn Fields (状态压缩DP)

题意:在由方格组成的矩形里面种草,相邻方格不能都种草,有障碍的地方不能种草,问有多少种种草方案(不种也算一种方案)。

分析:方格边长范围只有12,用状态压缩dp好解决。

预处理:每一行的障碍用一个状态保存好     每一行不考虑障碍的所有符合要求的状态保存好     第一行的方案数记录好。

然后一行一行递推,每一行只与上一行有关。


#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <climits>//形如INT_MAX一类的
#define MAX 100005
#define INF 0x7FFFFFFF
#define mod 100000000
//#pragma comment(linker, "/STACK:36777216") ///传说中的外挂
using namespace std;

int map[15][15];
int dp[15][1 << 12];
int buff[1 << 12]; //保存每一行不考虑障碍的状态
int bar[15]; //保存每一行的障碍的状态
int n,m,sum,ans;

void getbuff() {
    int total = 1 << m;
    for(int i=0; i<total; i++) {
        if(i & (i >> 1)) continue;
        buff[sum++] = i;
    }
}

void solve() {
    for(int i=1; i<n; i++) {
        for(int j=0; j<sum; j++) {
            if(buff[j] & bar[i]) continue;
            for(int k=0; k<sum; k++) {
                if(buff[j] & buff[k]) continue;
                if(buff[k] & bar[i-1]) continue; //注意也要判冲突与否
                dp[i][buff[j]] = (dp[i][buff[j]] + dp[i-1][buff[k]]) % mod;
            }
        }
    }
    ans = 0;
    for(int j=0; j<sum; j++) {
        ans = (ans + dp[n-1][buff[j]]) % mod;
    }
}
int main(){
    scanf("%d%d",&n,&m);
    memset(dp,0,sizeof(dp));
    memset(bar,0,sizeof(bar));
    sum = 0;
    for(int i=0; i<n; i++) {
        for(int j=0; j<m; j++) {
            scanf("%d",&map[i][j]);
            if(map[i][j] == 0) {
                int move = m - j - 1;
                bar[i] += 1 << move;
            }
        }
    }
    getbuff();
    for(int j=0; j<sum; j++) {
        if(buff[j] & bar[0]) continue; // 注意
        dp[0][buff[j]] = 1;
    }
    solve();
    printf("%d\n",ans);
    return 0;
}


你可能感兴趣的:(POJ 3254 Corn Fields (状态压缩DP))