zoukankan      html  css  js  c++  java
  • poj2411 Mondriaan's Dream (用1*2的矩形铺)

    Description

    Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series' (where he had to use his toilet paper to draw on, for all of his paper was filled with squares and rectangles), he dreamt of filling a large rectangle with small rectangles of width 2 and height 1 in varying ways. 

    Expert as he was in this material, he saw at a glance that he'll need a computer to calculate the number of ways to fill the large rectangle whose dimensions were integer values, as well. Help him, so that his dream won't turn into a nightmare!

    Input

    The input contains several test cases. Each test case is made up of two integer numbers: the height h and the width w of the large rectangle. Input is terminated by h=w=0. Otherwise, 1<=h,w<=11.

    Output

    For each test case, output the number of different ways the given rectangle can be filled with small rectangles of size 2 times 1. Assume the given large rectangle is oriented, i.e. count symmetrical tilings multiple times.

    Sample Input

    1 2
    1 3
    1 4
    2 2
    2 3
    2 4
    2 11
    4 11
    0 0
    

    Sample Output

    1
    0
    1
    2
    3
    5
    144
    

    51205

    这题可以用状压dp做,用二进制表示每一行的状态,横着的11表示横放,竖着的01表示竖放,然后先初始化第一行的可行状态,因为第一行前没有空行,所以转化后的二进制中如果有奇数个1连一起一定是不可行状态.但对于大于1的行来说,因为可能会有前面一行的矩形竖着放,所以奇数个1连在一起可能是可行的,所以需要另外的判断。可以发现,状态转移过程中,大于1的每一行都要满足两个条件,一个是行内不能有空余的位置(可以用|来实现,很神奇啊),另一个是如果去掉前一行竖着放的矩形遗留在当前行的1,当前状态一定也是可行状态(可以用&来实现,动手画一下),这样就可以把动态转移方程写出来了,我们记dp[i][state]为第i行state状态下的总方案数,那么dp[i][state]=dp[i][state]+dp[i-1][state'],所以最后要求的就是dp[n][(1<<m)-1].

    #include<stdio.h>
    #include<string.h>
    #define ll long long
    int kexing[5000],n,m;
    ll dp[15][5000];
    int panduan(int x)
    {
    	int i,j,tot=0;
    	while(x>0){
    		if(x%2==1){
    			tot++;x=x/2;
    		}
    		else{
    			if(tot%2==1)return 0;
    			tot=0;x=x/2;
    		}
    	}
    	if(tot%2==1)return 0;
    	else return 1;
    }
    
    int check(int x,int y)
    {
    	int i,j,t=(1<<m)-1;
    	if(!( (x|y)==t ) )return 0;
    	return kexing[x&y];
    }
    
    int main()
    {
    	int i,j,k;
    	while(scanf("%d%d",&n,&m)!=EOF)
    	{
    		if(n==0 && m==0)break;
    		memset(dp,0,sizeof(dp));
    		for(i=0;i<(1<<m);i++){
    			if(panduan(i)){
    				kexing[i]=1;dp[1][i]=1;
    			}
    			else kexing[i]=0;
    		}
    		for(i=2;i<=n;i++){
    			for(j=0;j<(1<<m);j++){
    				for(k=0;k<(1<<m);k++){
    					if(check(j,k)){
    						dp[i][j]=dp[i][j]+dp[i-1][k];
    					}
    				}
    			}
    		}
    		printf("%lld
    ",dp[n][(1<<m)-1]);
    	}
    	return 0;
    }



  • 相关阅读:
    动态规划入门到熟悉,看不懂来打我啊
    git 查看当前仓库地址以及设置新的仓库地址
    数字与字符串系列教材 (三)- Java Math类常用方法
    数字与字符串系列教材 (三)- Java Math类常用方法
    数字与字符串系列教材 (二)- Java中把数字转换为字符串,字符串转换为数字
    数字与字符串系列教材 (二)- Java中把数字转换为字符串,字符串转换为数字
    数字与字符串系列教材 (一)- Java中基本类型的装箱和拆箱
    数字与字符串系列教材 (一)- Java中基本类型的装箱和拆箱
    接口与继承系列教材 (十)- Java 内部类详解
    接口与继承系列教材 (十)- Java 内部类详解
  • 原文地址:https://www.cnblogs.com/herumw/p/9464733.html
Copyright © 2011-2022 走看看