• 状压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]);
        }
     }
     
     
     
     
  • 相关阅读:
    Luogu P1396 营救
    Luogu P1339 热浪Heat Wave
    哈夫曼树学习笔记
    题解 CF1372C
    题解 CF 1372 B
    题解 CF 1372A
    题解 UVA1193 Radar Installation
    题解 洛谷 P2287 [USACO07NOV]Sunscreen G
    洛谷 P1080 国王游戏 题解
    牛客练习赛 66C公因子 题解
  • 原文地址:https://www.cnblogs.com/dancer16/p/6852679.html
Copyright © 2020-2023  润新知