zoukankan      html  css  js  c++  java
  • poj 2411 Mondriaan's Dream 【dp】

    题目:poj 2411 Mondriaan's Dream


    题意:给出一个n*m的矩阵,让你用1*2的矩阵铺满,然后问你最多由多少种不同的方案。


    分析:这是一个比較经典的题目。网上各种牛B写法一大堆。题解也是

    我们能够定义状态:dp【i】【st】:在第 i 行状态为 st 的时候的最慷慨案数、

    然后转移方程:dp【i】【st】 = sum (dp【i-1】【ss】)

    即全部的当前行都是由上一行合法的状态转移而来。

    而状态的合法性由两种铺法得到。第一种横放。注意要求前一行全满。然后竖放,上一行为空。能够留空。


    AC代码:

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const long long N = 15;
    long long dp[N][1<<N];
    long long ans[N][N];
    long long n,m;
    bool solve(long long st)
    {
        long long tmp=0;
        for(long long i=0; i<m; i++)
        {
            if(st&(1<<i))
                tmp++;
            else
            {
                if(tmp%2)
                    return false;
                tmp=0;
            }
        }
        if(tmp%2)
            return false;
        return true;
    }
    bool cmp(long long st,long long up)
    {
        for(long long i=0; i<m; i++)
        {
            if(st&(1<<i))
            {
                if(up&(1<<i))
                {
                    if(i==m-1 || !(st&(1<<(i+1))) || !(up&(1<<(i+1))))
                        return false;
                    else
                        i++;
                }//否则的话竖放
            }
            else
            {
                if(!(up&(1<<i)))
                    return false;
            }
        }
        return true;
    }
    int main()
    {
        memset(ans,0,sizeof(ans));
        while(~scanf("%lld%lld",&n,&m))
        {
            if(n==0 && m==0)
                break;
            if((m*n)%2)
            {
                printf("0
    ");
                continue;
            }
            if(m>n)
                swap(m,n);
            if(ans[n][m])
            {
                printf("%lld
    ",ans[n][m]);
                continue;
            }
            memset(dp,0,sizeof(dp));
            long long len = 1<<m;
            for(long long i=0; i<len; i++)
            {
                if(solve(i))
                    dp[1][i]=1;
            }
            for(long long i=2; i<=n; i++)
            {
                for(long long st=0; st<len; st++) //当前行
                {
                    for(long long k = 0; k<len; k++) //上一行
                    {
                        if(cmp(st,k))
                            dp[i][st]+=dp[i-1][k];
                    }
                }
            }
            printf("%lld
    ",dp[n][len-1]);
            ans[n][m] = dp[n][len-1];
        }
        return 0;
    }
    


  • 相关阅读:
    PHP json_decode()解析失败 返回NULL 错误是4
    PHP 合并两个二维数组 array_map 和 array_walk 的区别
    PHP二维数组指定字段进行排序
    常用正则汇总
    PHP中json_encode()使用须知,JSON数组和JSON对象
    PHPExcel大文件块级别读取 速度快 减少占用资源
    移动端border-radius失效
    JavaScript滑动页面到顶部
    软键盘把底部div顶上去
    JavaScript滚动div
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5226655.html
Copyright © 2011-2022 走看看