HDOJ 1400 & POJ 2411 - Mondriaan's Dream 状态压缩DP

    dp[r][k]代表第r行的占有情况是二进制k(0为空,1为已占)....每次更新枚举每行的情况..看怎么来摆..首先要保证摆的自我不冲突.然后它的更新来源可以推出来(因为每个方块最多影响其上一层的..而题目要求必须所有位置都填满..那么确定了本行的放置情况,其中竖着放回占有上面一行的一格,所以上行对应的就是0....不放或横着放必须保证上面已经占有.即上一行对应位置为1..)...


Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<set>
#include<algorithm>
#include<cmath>
#define oo 1000000007
#define ll long long
#define pi acos(-1.0)
#define MAXN 505
using namespace std;
int h,w,canuse[14000],num;
ll dp[15][2148];
bool legal(int x)
{
      int i,a[15];
      memset(a,0,sizeof(a)); 
      for (i=1;i<=w;i++)
      {
            if (x%3==1) a[i]++;
            if (x%3==2) a[i]++,a[i+1]++;
            x/=3;
      }
      if (a[w+1]>0) return false;
      for (i=1;i<=w;i++)
         if (a[i]>1) return false;
      return true;
}
bool canput(int x)
{ 
      x=canuse[x];
      while (x)
      {
             if (x%3==1) return false;
             x/=3;
      }
      return true;
}
int findit(int x)
{ 
      int i,data=0,t=1; 
      x=canuse[x];
      for (i=1;i<=w;i++)
      {
            if (x%3!=1) data+=t;
            x/=3;
            t*=2;
      }
      return data;
}
int _to2(int x)
{
      int i,a[13],data;
      memset(a,0,sizeof(a));
      x=canuse[x];
      for (i=1;i<=w;i++)
      {
            if (x%3==1) a[i]=1;
            if (x%3==2) a[i]=1,a[i+1]=1;
            x/=3;
      }
      data=0;
      for (i=1;i<=w;i++) data+=a[i]*(1<<(i-1));
      return data;         
}
int main()
{
      int i,r,j,totol; 
      while (~scanf("%d%d",&h,&w))
      {
             if (!h && !w) break;
             totol=1;
             for (i=1;i<=w;i++) totol*=3;
             num=0;
             for (i=0;i<totol;i++)
                 if (legal(i)) canuse[++num]=i;
             memset(dp,0,sizeof(dp));
             for (i=1;i<=num;i++) 
                if (canput(i)) dp[1][_to2(i)]=1;
             for (r=2;r<=h;r++)
                for (i=1;i<=num;i++) 
                  dp[r][_to2(i)]+=dp[r-1][findit(i)]; 
             printf("%I64d\n",dp[h][(1<<w)-1]);
      }
      return 0;
}


你可能感兴趣的:(HDOJ 1400 & POJ 2411 - Mondriaan's Dream 状态压缩DP)