zoukankan      html  css  js  c++  java
  • ZOJ1100 Mondriaan's Dream

    题目链接:QAQ

    大致题意:有一个m行n列的矩阵,用1*2的骨牌(可横放或竖放)完全覆盖,骨牌不能重叠,有多少种不同的覆盖的方法?

    Solution:

    (n,mle11),肯定是不能暴力的,又类似棋盘问题,一下就能想到状压dp

    对于每一列(或每一行)的状态用二进制表示,0表示放了,1表示没放,在转换回十进制存储。

    然后枚举一列的所有状态,看它可以转移到哪些状态,然后统计答案就行了。

    最后应该输出f[n+1][0],而不是f[n][n]。本题需要long long。

    Code:

    #include<cstdio>
    #include<cstring>
    #define N 10001
    #define ll long long
    using namespace std;
    int n,m;
    ll dp[15][2051];
    int a[15],b[15],c[2051][2051];
    void dfs(int x,int state){
        if(x==m+1){
            int k=0;
            for(int i=1;i<=m;i++) k=(k<<1)+b[i];
            c[state][k]=1;
            return ;
        }
        if(!a[x]){
            b[x]=1;
            dfs(x+1,state);
            if(!a[x+1]&&x+1<=m){
                b[x]=b[x+1]=0;
                dfs(x+2,state);
            }
        }else b[x]=0,dfs(x+1,state);
    }
    signed main(){
        begin:
        scanf("%d%d",&n,&m);
        if(n==0&&m==0) return 0;
        memset(c,0,sizeof(c));
        memset(dp,0,sizeof(dp));
        int num=(1<<m)-1;
        for(int i=0;i<=num;i++){
            int k=i;
            for(int j=m;j;j--) a[j]=k%2,k>>=1;
            dfs(1,i);
        }dp[1][0]=1;
        for(int k=1;k<=n;k++)
            for(int i=0;i<=num;i++)
                for(int j=0;j<=num;j++)
                    dp[k+1][j]=dp[k+1][j]+(c[i][j]*dp[k][i]);
        printf("%lld
    ",dp[n+1][0]);
        goto begin;
    }
    
  • 相关阅读:
    English Voice of <<Cups>>
    【线段树】奶牛排队(USACO 2007 January Gold)
    【线段树】买水果
    【线段树】卫星覆盖(NOI97)-矩阵切割
    插入排序 (Insertion Sort)
    选择排序 (Selection Sort)
    springboot整合redis
    redis入门及相关API
    mycat配置文件的详细介绍
    redis常用命令
  • 原文地址:https://www.cnblogs.com/NLDQY/p/10385951.html
Copyright © 2011-2022 走看看