pku 3254 Corn Fields 状态DP
http://poj.org/problem?id=3254
题意:
给定一个n*m的矩形,fj要在里面种玉米给奶牛吃,矩形内的小格中如果为1说明土地肥沃可以种植,如果为0说明土壤贫瘠不能种植玉米,而且奶牛们不喜欢在挨着的田地里吃玉米,问fj有多少种可选择方案种植玉米。
思路:
表示对状态dp不来感啊,首先dp[i][j]表示第i行在第j中状态下的可能数,则有dp[i][j] += dp[i - 1][k]这里k是在第i - 1行的所有状态中满足要求的状态。j也是在第i行满足要求的状态。
j,k满足要求的条件:1:满足当前行本身的种植条件;2:与上一行的种植情况要满足要求;
View Code
#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include <cmath> #define CL(a,num) memset(a,num,sizeof(a)) #define M 13 #define N 13 #define MOD 100000000 using namespace std; const int inf = 1999999; int map[N],dp[N][1<<M]; int state[1<<M],ct; int n,m,total; bool isok(int x) { if (x&(x<<1)) return false; else return true; } void init() { ct = 0; int i;//将满足条件的行状态记录,(这里是左右不相邻) for (i = 0; i < total; ++i) { if (isok(i)) state[ct++] = i; } } int main() { //freopen("din.txt","r",stdin); int a,i,j,k; scanf("%d%d",&n,&m); CL(map,0); for (i = 0; i < n; ++i) { for (j = 0; j < m; ++j) { scanf("%d",&a); if (a == 0) map[i] |= (1<<j);//记录每一行的本身的种植条件 } } total = (1<<m); init(); CL(dp,0); //初始化第一行 for (i = 0; i < ct; ++i) { if (!(map[0]&state[i])) dp[0][state[i]]++; } for (i = 1; i < n; ++i) { for (j = 0; j < ct; ++j) { if (!(map[i]&state[j]))//首先满足自身的种植条件 { for (k = 0; k < ct; ++k)//枚举i - 1行里面所有满足的状态k { if (!(map[i - 1]&state[k]) && !(state[k]&state[j])) { dp[i][state[j]] += dp[i - 1][state[k]]; } } } } } int ans = 0; for (i = 0; i < ct; ++i) { if (!(state[i]&map[n - 1])) ans += dp[n - 1][state[i]]; ans %= MOD; } printf("%d\n",ans); return 0; }