zoukankan      html  css  js  c++  java
  • POJ2411

    题目大意

    给定一个N*M大小的地板,要求你用1*2大小的砖块把地板铺满,问你有多少种方案?

    题解

    刚开始时看的是挑战程序设计竞赛上的关于铺砖块问题的讲解,研究一两天楞是没明白它代码是怎么写的,智商捉急,上面是用逐格进行转移的,据说神马插头DP。。。坑爹啊。。。然后果断放弃研究了。。。我们还是逐行的进行转移,这样比较好理解,方程表示为:dp[i][j]+=dp[i-1][k](能够从上一行的状态k转移到当前状态j)。我们需要枚举出符合要求的状态j和k,如果第i-1行p列没有放,那么第i行的p列肯定需要放置一个竖块,如果第i-1行p列放了,那么i行的p列可以不用放,如果第i-1行的p列和p+1列都放了,那么我们可以在第i行的p列和p+1列横着放置一个砖块。

    我们用dfs实现,那么上述三种情况可以分别表示为

    dfs(step+1,s1<<1|1,s2<<1,line); 竖放
    dfs(step+1,s1<<1,s2<<1|1,line);不放
    dfs(step+2,s1<<2|3,s2<<2|3,line);横放

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define MAXN 15
    typedef long long LL;
    LL dp[MAXN][1<<MAXN];
    int n,m;
    void dfs(int step,int s1,int s2,int line)
    {
        if(step==m)
        {
            dp[line][s1]+=dp[line-1][s2];
            return;
        }
        dfs(step+1,s1<<1|1,s2<<1,line);
        dfs(step+1,s1<<1,s2<<1|1,line);
        if(step+2<=m)
            dfs(step+2,s1<<2|3,s2<<2|3,line);
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF&&(n+m))
        {
            memset(dp,0,sizeof(dp));
            dp[0][(1<<m)-1]=1;
            for(int i=1; i<=n; i++)
                dfs(0,0,0,i);
            printf("%I64d
    ",dp[n][(1<<m)-1]);
        }
        return 0;
    }
  • 相关阅读:
    Git 生命周期
    Git 配置环境
    JAVA克隆对象报错:The method clone() from the type Object is not visible
    C# 将字符串按要求分解成字符串数组
    servlet 标红的错误笔记
    TIBCO Jaspersoft Studio 报表软件使用教程
    错误笔记4
    ^按位运算详解
    表现层状态转换
    servlet 读取文件
  • 原文地址:https://www.cnblogs.com/zjbztianya/p/3446410.html
Copyright © 2011-2022 走看看