题解/算法 {291. 蒙德里安的梦想}

题解/算法 {291. 蒙德里安的梦想}

LINK: https://www.acwing.com/problem/content/293/;

(i,j): 覆盖[0...i]行, 且第`i`行的状态为`j` (比如, j中的第k位二进制为1, 则说明有一个`(i,k),(i+1,k)`的竖板;

op{ st: 行状态[0,(1<<M))}

SET(i,j): { [op0, op1, ..., opi]}

DP(i,j): SET(i,j)的大小;
void __Solve(){
    int N, M;
    auto Is_valid = [&]( int _st) -> bool{
        int c = 0;
        for( int i = 0; i < M; ++i){
            if( (_st >> i) & 1){
                if( c & 1) return false;
                c = 0;
            }
            else ++ c;
        }
        if( c & 1) return false;
        return true;
    };
    while( true){
        cin>> N>> M;
        if( N == 0 && M == 0) break;
        //> (0, ?)
        for( int st = 0; st < (1 << M); ++st){
            auto & curDP = DP[ 0][ st];
            if( Is_valid( st)) curDP = 1;
            else curDP = 0;
        }
        //> (>0, ?)
        for( int row = 1; row < N; ++row){
            for( int st = 0; st < (1 << M); ++st){
                auto & curDP = DP[ row][ st];
                curDP = 0;

                for( int pre_st = 0; pre_st < (1 << M); ++pre_st){
                    if( pre_st & st) continue;
                    if( false == Is_valid( pre_st | st)) continue;
                    curDP += DP[ row - 1][ pre_st];
                }
            }
        }
        cout<< DP[ N - 1][ 0] ED_;
    }
}

错误

你可能会设置一个合法状态的集合, 里面每个状态 都满足 为0的连续子段 长度为偶数;
比如M=5, 第一行肯定不会是st=00000这个状态 (因为你放2个横板, 总是会空余一个, 而这个空余的 下一行是不管的),因此 这个状态 对于第一行 确实是非法的;
. 但你可能会认为 00000这个状态 对其他所有行 都是非法的, 这是错误的… 因为这个空余位 可以来自于 上一行的 竖板 (第一行没有上一行, 可以其他行都有上一行的);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值