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;

}


 

 

你可能感兴趣的:(Field)