Processing math: 100%

LUOGU P1879 [USACO06NOV]Corn Fields G

快被做烂的方案数状压DP

设状态为一个正整数 S ,其在二进制的第 i 位若为 1 则表示在这一块有草地

例如 S=(0010)2 表示在第 2 列有草地,而其他列没有草地

那么 设 f(i,S) 表示 在第 i 行 状态为 S 时的最优解

状态转移方程即 f(i,S)=f(i1,p) 其中 p 合法

因为这道题限定了状态,即限定了那些地方肥沃

为了解决这个问题 我引入了 mp 数组

mp(i) 表示第 i...

for(int i=1;i<=m;++i)
    for(int j=1;j<=n;++j) {
        scanf("%d",&x);
        mp[i] |= (x^1)<<(j-1);
    } // 读入

rt,若允许的每行的最大状态为 (1110)2mp(i)=(0001)2

那么状态转移方程的条件就可以列出来了

即 每个状态 S 满足 !(j&(j<<1)||j&mp[i])

每个状态 p 满足 !(p&(p<<1)||p&mp[i-1])

然后就能快乐的打代码了

// P1879 [USACO06NOV]玉米田Corn Fields
// 设计状态
// f[i][j] 表示 在第i行 状态为j时的最优解
// f[i][j] = sigma(f[i-1][p])
#include<bits/stdc++.h>
using namespace std;
const int p = (int)1e8;
long long f[13][1<<12];
int mp[13],m,n,x;
int main() {
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;++i)
        for(int j=1;j<=n;++j) {
            scanf("%d",&x);
            mp[i] |= (x^1)<<(j-1);
        }
    for(int i=0;i<(1<<n);++i) if(!(i&mp[1]||i&(i<<1))) f[1][i] = 1;
    for(int i=2;i<=m;++i)
        for(int j=0;j<(1<<n);++j) {
            if(j&(j<<1)||j&mp[i]) continue ;
            for(int k=0;k<(1<<n);++k) {
                if(j&k||k&mp[i-1]) continue ;
                f[i][j] = (f[i][j] + f[i-1][k]) % p;
            }
        }
    long long ans = 0;
    for(int i=0;i<(1<<n);++i) ans = (ans + f[m][i]) % p;
    printf("%lld",ans);
    return 0;
}
posted @   AxDea  阅读(119)  评论(0编辑  收藏  举报
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(三):用.NET IoT库
· 【非技术】说说2024年我都干了些啥
点击右上角即可分享
微信分享提示