zoukankan      html  css  js  c++  java
  • 状压DP入门——铺砖块

    题目描述

    现有n*m的一块地板,需要用1*2的砖块去铺满,中间不能留有空隙。问这样方案有多少种 

    输入

    输入n,m(1<=n, m<=11) 
    有多组输入数据,以m=n=0结束 

    输出

    输出铺砖块的方案数

    样例输入

    1 2 1 3 1 4 2 2 2 3 2 4 2 11 4 11 0 0

    样例输出

    1 0 1 2 3 5 144 51205
    我A的第一道状压DP题是导游,感觉就是背包~~
    此题不是很懂
    此题状压DP,DP[i][sta]表示前i行填满对第i+1行的影响为状态sta时的方案总数
    易知DP[0][0]=1;目标值DP[i][0];
    关于sta:sta表示当前此行对下一行的影响
    定义竖铺时上一行为1,这一行为0;横铺时均为0;
    可以推得状态若上一行为1,这一行必为0(竖铺一块嘛);
    若上一行为0,可以竖铺一块填满下面的一块,这样下一行就为0;
    若上一行为00,下一行为00;
    关于DP的转移:dfs生成每个前一行和后一行的状态
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    long long  n,m,num,dp[150][40970],change[40970][20];
    void dfs(int l,int pre,int now)
    {
        if(l>m)
        return;
        if(l==m)
        {
            change[++num][0]=pre;
            change[num][1]=now;
        }
        dfs(l+1,pre<<1,now<<1|1);
        dfs(l+2,pre<<2,now<<2);
        dfs(l+1,pre<<1|1,now<<1);
    }
    int main()
    {
        while(~scanf("%d %d",&n,&m)&&n!=0&&m!=0)
        {
            if(n>m) swap(n,m);
            num=0;
            dfs(0,0,0);
            memset(dp,0,sizeof(dp));
            dp[0][0]=1;
            rep(i,1,n)
            
            {
                rep(j,1,num)
                {
                    dp[i][change[j][1]]+=dp[i-1][change[j][0]]; 
                }
            }
            printf("%lld
    ",dp[n][0]);
        }
     }
     
     
     
     
  • 相关阅读:
    VS2008编写MFC程序--使用opencv2.4()
    November 02nd, 2017 Week 44th Thursday
    November 01st, 2017 Week 44th Wednesday
    October 31st, 2017 Week 44th Tuesday
    October 30th, 2017 Week 44th Monday
    October 29th, 2017 Week 44th Sunday
    October 28th, 2017 Week 43rd Saturday
    October 27th, 2017 Week 43rd Friday
    October 26th, 2017 Week 43rd Thursday
    October 25th, 2017 Week 43rd Wednesday
  • 原文地址:https://www.cnblogs.com/dancer16/p/6852679.html
Copyright © 2011-2022 走看看