zoukankan      html  css  js  c++  java
  • 哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(高年级)B 小乐乐搭积木 (状态压缩)

    时间限制:C/C++ 1秒,其他语言2秒

    空间限制:C/C++ 32768K,其他语言65536K
    64bit IO Format: %lld

    题目描述

    小乐乐想要给自己搭建一个积木城堡。
    积木城堡我们假设为n*m的平面矩形。
    小乐乐现在手里有1*2,2*1两种地砖。
    小乐乐想知道自己有多少种组合方案。

    输入描述:

    第一行输入整数n,m。(1<=n,m<=10)

    输出描述:

    输出组合方案数。
    示例1

    输入

    复制
    2 3

    输出

    复制
    3

    说明

    示例2

    输入


    1 3

    输出

    复制
    0
    示例3

    输入


    2 5

    输出


    8

    题目大意:

    给你一块n*m的方块,以及若干1*2的小木板,问你有多少种方式能够使小木板填满方块。

    状压DP模板题。和POJ2411雷同。

    摘自focus_best的csdn博客:

    首先我们定义如下这种填充表示方式:如果一个骨牌是横着放的,那么它所在的两个方格都填充1.如果它是竖着放的,那么它所在的两个格子中,上面的那个填0,下面的这个填1.由此可以得到断言:该矩阵的骨牌摆放方法和该矩阵的二进制表示法是一一对应的。 

    现在我们专注于这个问题:如何求相邻两行二进制值的对应关系?可以枚举i-1行的所有二进制值情况,然后判断这个值本身是否合法,如果合法(其实只要这行是中间行所有二进制值都合法的,因为首行我们虚构了第0行为全1序列,最后一行我们只需要全1序列对应的值),再通过它推断出和它兼容的第i行二进制值(和i-1行二进制值兼容的第i行二进制为:第i-1行为0的位,第i行应为1。第i-1行为1的位,第i行为0或1,且如果第i行为1那么表示第i行此时的对应位置是横着放的,应该有偶数个连续的1才合法,只需判断i-1行中为1的位在第i行中如果也为1必须偶数个这样的1相连)。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <map>
    #include <set>
    typedef long long ll;
    const int mod=1000000007;
    const int inf=1000000000;
    const int maxn=10;
    const int maxm=200;
    
    int n,m;
    int dp[maxn+5][2<<(maxn+5)];
    
    int main()
    {
        scanf("%d%d",&n,&m);
        memset(dp,0,sizeof(dp));
        dp[0][(2<<(m-1))-1]=1;
    
        for(int i=1; i<=n; i++)
        {
            for(int k=0; k<=((2<<(m-1))-1); k++)//i行
            {
                if(i==n&&k<((2<<(m-1))-1))
                    continue;
                for(int j=0; j<=((2<<(m-1))-1); j++)//i-1行
                {
                    bool flag=true;
                    for(int p=0,cnt=0; p<=m-1; p++)
                    {
                        if((j&(1<<p))==0)
                        {
                            if(cnt%2)
                                flag=false;
                            else
                                cnt=0;
                            if((k&(1<<p))==0)
                                flag=false;
                        }
                        if((j&(1<<p))>0)
                        {
                            if((k&(1<<p))>0)
                                cnt++;
                            else
                            {
                                if(cnt%2)
                                    flag=false;
                                else
                                    cnt=0;
                            }
                        }
                        if(p==m-1)
                        {
                            if(cnt%2)
                                flag=false;
                        }
                        if(!flag)
                            break;
                    }
                    if(flag)
                    {
                        dp[i][k]+=dp[i-1][j];
                    }
                }
            }
        }
    
        printf("%d
    ",dp[n][((2<<(m-1))-1)]);
    
        return 0;
    }
    View Code
  • 相关阅读:
    Python 中特殊变量/方法命名规则说明(特别是私有变量)及使用实例
    博客(文本)编辑工具Markdown使用初体验
    Vue2.0关于生命周期和钩子函数
    Vue2.0中的路由配置
    Vue项目中引入外部文件(css、js、less)
    利用vue-cli创建Vue项目
    vue+webpack构建项目
    VueJs2.0建议学习路线
    Python基础 :正则表达式
    Python框架 :WEB框架
  • 原文地址:https://www.cnblogs.com/acboyty/p/10061960.html
Copyright © 2011-2022 走看看