• POJ 2411 Mondriaan's Dream


    思路:状态压缩dp,如果在(i,j)位置横着放砖块,那么(i,j)和(i+1.j)都是1,如果竖着放砖块,那么(i,j)为0,(i,j+1)为1,这样每行就可以用一个整数来存放状态,设dp[i][j]为第i行为j状态时得摆放方案数,那么最终要求的结果就是dp[n][(1 << m)-1];

    由于第i行如何摆放只受第i-1行状态的影响,所以状态转移方程为:dp[i][j] = sum(dp[i-1][k]),其中状态第i行的状态j和第i-1行的状态k应兼容,即不发生冲突。

    下面说说具体兼容情形:

    1,若(i,j)位置为1,那么{

    (1)若(i-1,j为0,这块砖是竖着放,那么可能是兼容的,直接检查(i,j+1)位置;

    (2)若(i-1,j)为1,那么这块砖必须横着放,因此(i,j+1)必须为1,并由此可得(i-1,j+1)也必须是1,若满足这些就检查(i,j+2)位置;

    }

    2,若(i,j)位置为0,那么{

    (i-1,j)位置必须为1,因为不可能连续两个竖着放的砖块“头对头”,如果满足就直接检查(i,j+1)位置;

    }


    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define LL long long int
    using namespace std;
    const int MAXN = 15;
    int n,m;
    LL ans[MAXN][MAXN];
    LL dp[MAXN][1 << 12];
    bool init(int s){
        for(int i = 0;i < m;){
            if(s & (1 << i)){
                if(i == m-1) return false;
                if(s & (1 << (i+1))) i += 2;
                else return false;
            }else i++;
        }
        return true;
    }
    bool canPalce(int s1,int s2){
        for(int i = 0;i < m;){
            if(s1 & (1 << i)){
                if(s2 & (1 << i)){
                    if(i == m-1 || !(s1&(1<<(i+1))) || !(s2&(1<<(i+1)))) return false;
                    i += 2;
                }else i ++;
            }else{
                if(s2 & (1 << i)) i ++;
                else return false;
            }
        }
        return true;
    }
    void solve(int n,int m){
        memset(dp,0,sizeof dp);
        int range = (1 << m);
        for(int i = 0;i < range;i ++)
            if(init(i)) dp[1][i] = 1;
        for(int i = 2;i <= n;i ++){
            for(int j = 0;j < range;j ++){
                for(int k = 0;k < range;k ++)
                    if(canPalce(j,k)) dp[i][j] += dp[i-1][k];
            }
        }
        ans[n][m] = dp[n][range-1];
        cout << ans[n][m] << endl;
    }
    int main(){
        memset(ans,-1,sizeof ans);
        while(~scanf("%d%d",&n,&m) && n+m){
            if(n < m) swap(n,m);
            if(ans[n][m] != -1){
                cout << ans[n][m] << endl;
                continue;
            }else if(n*m & 1){
                ans[n][m] = 0;
                cout << 0 << endl;
                continue;
            }else solve(n,m);
        }
    }


  • 相关阅读:
    标准化R包开发流程
    创建Rdemo项目
    rJava在ubuntu上的安装
    Linux初始root密码设置
    检查网卡错误
    统计学习方法-李航 第一章
    ubuntu16.04细节设置
    linux指令学习
    Python在ubuntu16.04上环境搭建
    kuberneets 1.17 设置 kube-reserved, system-reserved
  • 原文地址:https://www.cnblogs.com/anhuizhiye/p/3933144.html
Copyright © 2020-2023  润新知