3254: 玉米田(POJ)

3254: 玉米田(POJ)

题目描述

约翰购买了由m ×n (1≤m ,n ≤12) 的方格组成的矩形牧场,想在一些方格上种玉米。遗憾的是,有些方 格土壤贫瘠,无法种植。约翰在选择种植哪些方格时,会避免选择相 邻的方格,没有两个选定的方格共享一条边。约翰考虑了所有可能的 选择,他认为没有选择方格也是一种有效的选择!帮助他选择种植方 格的方案数。

输入

第1行包含以两个空格分隔的整数m 和n。后面有m 行, 每行都包含n 个整数,表示一个方格是否肥沃(1表示肥沃,0表示贫瘠)。

输出

单行输出选择种植方格的方案数模100000000。

样例输入

2 3
1 1 1
0 1 0

样例输出

9

提示信息

按如下方式对肥沃的方格进行编号,仅在一个方格上种植 有4种方案(1、2、3或4),在两个方格上种植有3种方案(13、14或 34),在三个正方形上种植有1种方案(134),还有1种方案是所有方 格都不种植。所以一共有9种方案。

题解1(C++版本)

#include<cstdio>
using namespace std;

const int MOD = 100000000;
int m, n; //玉米田行数、列数 
int g[14]; //用十进制数保存每行的状态值,用二进制表示状态 
int dp[14][1<<14]; //dp[i][a]表示已经种植前i行,第i行第a个状态时的方案数 
int cnt; //一行的合法状态个数 
int s[1<<14]; //一行的合法状态集,每行的初始合法状态集是相同的 

int main(){
	scanf("%d%d", &m, &n);
	for(int i = 1; i <= m; i++){
		for(int j = 1,x; j <= n; j++){
			scanf("%d", &x);
			g[i] = (g[i]<<1) + x; // 输入三个数(1 1 1),则g[i]=111 
		}
	} 
	// 预处理 
	for(int i = 0; i < (1<<n); i++){ //枚举一行所有的状态 
		if(!(i&(i>>1))) s[cnt++] = i; //保存一行的初始合法状态 
	}
	dp[0][0] = 1; //什么都不种植,也是一种方案 
	for(int i = 1; i <= m + 1; i++){ //枚举行 
		for(int a = 0; a < cnt; a++){ //枚举第i行的初始合法状态 
			for(int b = 0; b < cnt; b++){ //枚举第i - 1行的初始合法状态 
				if((s[a]&g[i]) == s[a] && !(s[a]&s[b])){ //题目中的约束条件 
					dp[i][a] = (dp[i][a] + dp[i - 1][b]) % MOD;
				}  //'&'运算符的优先级低于'=='运算符的优先级 
			}
		}
	}
	printf("%d\n", dp[m + 1][0]); //相当于只在1~n行种植 
	return 0;
}
  • 22
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值