ybtoj 状压DP课堂过关 例题1jzoj 1266 luogu P1879 [USACO06NOV]Corn Fields G & 玉米田 & 种植方案
Posted SSL_ZZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ybtoj 状压DP课堂过关 例题1jzoj 1266 luogu P1879 [USACO06NOV]Corn Fields G & 玉米田 & 种植方案相关的知识,希望对你有一定的参考价值。
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);
}
以上是关于ybtoj 状压DP课堂过关 例题1jzoj 1266 luogu P1879 [USACO06NOV]Corn Fields G & 玉米田 & 种植方案的主要内容,如果未能解决你的问题,请参考以下文章
luogu UVA10559 ybtoj 区间DP课堂过关 例题3消除木块 & 方块消除 Blocks