码迷,mamicode.com
首页 > 其他好文 > 详细

poj3254

时间:2016-08-12 13:12:38      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:

一道状态压DP题目。将每一行进行编码,1表示种0表示不种。首先求解出每一行合法的状态集合。对于第i行状态j,如果j&(j<<1)==0并且对于该行为0的地方j在当前位的二进制也是0,则表明状态j合法。用dp[i][j]表示第i行状态为j时(j合法的)的方法数,得到状态转移方程如下:

     dp[i][j]=sum(dp[i-1][k]) j&k==0  ;在计算dp[i][j]时,可以枚举上一行的所有状态。

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<vector>
using namespace std;
int const SIZE = 13;
typedef long long LL;
const int mod = 100000000;
vector<int> vec[SIZE];  //保存第i行合法状态
int a[SIZE][SIZE];
LL dp[SIZE][1 << 13];
int bit[SIZE];
int m, n;
int main(){
	int i, j,k;
	bit[0] = 1;
	for (i = 1; i < SIZE; i++)
		bit[i] = bit[i - 1] * 2;
	while (~scanf("%d%d", &n, &m)){
		for (i = 1; i <= n;i++)
		for (j = 1; j <= m; j++)
			scanf("%d", &a[i][j]);
		for (i = 0; i <= n; i++)
			vec[i].clear();    //初始化清空
		//计算每一行合法状态并保留在vec中
		vec[0].push_back(0);
		for (i = 1; i <= n; i++){
			for (j = 0; j < bit[m]; j++){
				if ((j&(j << 1)))
					continue;
				for (k = 1; k <= m; k++){
					if ((a[i][k] == 0) && (bit[k - 1] & j)!= 0)
						break;
				}
				if (k == m + 1)
					vec[i].push_back(j);
			}
		}
		memset(dp, 0, sizeof(dp));
		dp[0][0] = 1;//0块土地时候什么也不种,也是一种方法
		for (i = 1; i <= n; i++){
			for (j = 0; j < (int)vec[i].size(); j++){
				for (k = 0; k < (int)vec[i - 1].size(); k++){
					if (!(vec[i - 1][k] & vec[i][j])){   //状态相容
						dp[i][j] += dp[i - 1][k];
						dp[i][j] %= mod;
					}
				}
			}
		}
		LL ans = 0;
		for (i = 0; i < (int)vec[n].size(); i++){
			ans += dp[n][i];
			ans %= mod;
		}
		printf("%I64d\n", ans);
	}
	return 0;
}

  

poj3254

标签:

原文地址:http://www.cnblogs.com/td15980891505/p/5764370.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!