【ybtoj 状压DP课堂过关 例题1】【jzoj 1266】 【luogu P1879】 [USACO06NOV]Corn Fields G & 玉米田 & 种植方案

72 篇文章 1 订阅
57 篇文章 0 订阅

【例题1】种植方案 & 玉米田


Link

ybtoj【状压DP课堂过关】【例题1】种植方案
jzoj 【1266】 玉米田
luogu 【P1879】 [USACO06NOV]Corn Fields G
题面//因为不知道侵不侵权所以就是题面是私密的,有账号的直接看转送门就可了


解题思路

yyy只能选3个专栏(jzoj,ybtoj,luogu,DP)yyy

好家伙,这题是有多经典,三个链接
luogu那个都是一年前写的了,早没印象了,但是我写了博客

设 f[i][j] 为第 i 行,种植状态为 j 的方案数
转移蛮简单的,就枚举一下上一轮的状态,看一下状态合不合法就行

如果直接枚举状态时间会炸(1111 1111 1111 = 4095)
提前统计一下合法的状态(相邻没有1)


Code

#include <iostream> 
#include <cstdio>
#define P 100000000

using namespace std;

int n, m, x, num, ans;
int now[15], use[4100], f[15][4100];

int main() {
//	freopen("cowfood.in", "r", stdin);
//	freopen("cowfood.out", "w", stdout);
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= m; j ++) {
			scanf("%d", &x);
			now[i] = (now[i] << 1) + x;  //每行的可否种植的状态
		}
	for(int i = 0; i < (1 << m); i ++)
		if(!(i & (i >> 1)))  //相邻没有1
			use[++ num] = i;
	f[0][0] = 1;  //不种也是一种方案
	for(int i = 1; i <= n; i ++)
		for(int a = 1; a <= num; a ++) {
			if( !( ( use[a] & now[i] ) == use[a] ) ) continue;
			  //确保当行状态中种植的点是可以种的(不是贫瘠的土地,好家伙这字我都不会念)
			for(int b = 1; b <= num; b ++)
				if(!(use[a] & use[b]))  //两行之间没有上下相邻的 1
					f[i][use[a]] = (f[i][use[a]] + f[i - 1][use[b]]) % P;
		}
	for(int i = 1; i <= num; i ++)
		if( ( use[i] & now[n] ) == use[i] )
			ans = (ans + f[n][use[i]]) % P;
	printf("%d", ans);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值