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

    题目链接:https://vjudge.net/problem/POJ-2411

    题意:给出n*m的棋盘格,要求用1*2或2*1的长方形完全覆盖,求方案数

    并没有想出来这题,于是看了进阶指南。书上的状态设计的很巧妙:设f[i][s]表示到第i行,且第i行的状态为s的方案数。这儿s的某一位为1,表示它是2x1的上半部分;为0则是下半部分,或者1x2的某一格。那么有f[i][s]+=f[i-1][s2],此处s2表示上一行的状态。其中要保证:

    1)s&s2==0,因为不能上下两格都是2x1的上半部分

    2)s|s2这个状态中,不存在两个1之间有奇数个0,否则1x2无法摆放。

    初始化为f[0][0]=1,最后答案为f[n][0],某个状态是否有奇数个连续0,可以预处理得到

    #include<iostream>
    #include<cstring>
    #define ll long long
    using namespace std;
    
    int a[(1<<12)],b[12],n,m,i,j,s,s2;
    ll f[12][(1<<12)];
    
    int main(){
    	while (cin>>n>>m){
    	  if (n==0) break;
    	  memset(b,0,sizeof(b));
    	  memset(f,0,sizeof(f));
    	  memset(a,0,sizeof(a));
    	  b[m]=1;
    	  for (s=0;s<(1<<m);s++){
    	  	for (i=0;i<m;i++) b[i]=s&(1<<i);
    	  	j=0; int flag=0;
    	  	while (j<=m){
    	  	  int num=0;
    	  	  while (!b[j]) {j++; num++;}
    	  	  if (num%2) {
    	  	    flag=1; break;	
    		  }
    		  j++;
    		}
    		if (!flag) a[s]=1;
    	  }
    	  f[0][0]=1; //*
    	  for (i=1;i<=n;i++)
    	    for (s=0;s<(1<<m);s++)
    	      for (s2=0;s2<(1<<m);s2++)
    	        if ((s&s2)==0&&a[s2|s]) //*
    			  f[i][s]+=f[i-1][s2];
    	  cout<<f[n][0]<<endl;
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    2017.1.10学习笔记
    v-model双向绑定
    指令之v-bind
    v-for列表渲染
    事件修饰符
    v-on
    指令v-text v-html
    vue起步
    Swoole HTTPServer
    SwooleTCP
  • 原文地址:https://www.cnblogs.com/edmunds/p/13667398.html
Copyright © 2011-2022 走看看