sgu131

状态压缩 dp

f[i][t] 是指前 i1 行填满,第 i 行状态为 t 的方案数

full 为将一行填满的状态,可知
t ^full <=> 将 t 填满的方案
t <=> 将 t ^full 填满的方案

本题比较适合 DFS 逐行 dp
row 行状态为 t1,row+1 行状态为 t2
s1 列影响 s 列状态为 p1,p2

下面分7种情况讨论:
(1)当我们不在当前行当前列放 block

      0 0 
0 0
dfs(s+1,t1<<1|p1, t2<<1|p2,0 ,0);

(2)当横着放 block 时,即为:

      1 1 
0 0
dfs(s+1,t1<<1|1,t2<<1|p2,1,0); | p1 = 0

(3)当竖着放 block 时,即为:

      1 0 
1 0
dfs(s+1,t1<<1|1,t2<<1|1,0,0); | p1 = 0 & p2 = 0

(4)当 L 形如此放时,即为:

      1 0 
1 1
dfs(s+1,t1<<1|1,t2<<1|1,0,1); | p1 = 0 & p2 = 0

(5)当 L 形如此放时,即为:

      1 1 
1 0
dfs(s+1,t1<<1|1,t2<<1|1,1,0); | p1 = 0 & p2 = 0

(6)当 L 形如此放时,即为:

      0 1 
1 1
dfs(s+1,t1<<1|1,t2<<1|p2,1,1); | p2 = 0

(7)当 L 形如此放时,即为:

      1 1 
0 1
dfs(s+1,t1<<1|1,t2<<1|p2,1,1); | p1 = 0



#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>

const int MAXN = 11;

int n,m;
long long f[MAXN][1<<MAXN] = {0};
int full , row;

void dfs(int s , int t1 , int t2 , int p1 , int p2)
{

    if(s > m)
    {
        if(!p1 && !p2)f[row+1][t2] += f[row][t1^full];  
        return ;
    } 

    dfs(s+1,t1<<1|p1, t2<<1|p2,0 ,0);

    if(!p1)
    {  
      dfs(s+1,t1<<1|1,t2<<1|p2,1,0);  
      dfs(s+1,t1<<1|1,t2<<1|p2,1,1);
    }
    if(!p2)
    {
      dfs(s+1,t1<<1|p1,t2<<1|1,1,1);    
    }
    if((!p1) && (!p2))
    {
      dfs(s+1,t1<<1|1,t2<<1|1,0,0); 
      dfs(s+1,t1<<1|1,t2<<1|1,0,1); 
      dfs(s+1,t1<<1|1,t2<<1|1,1,0); 
    }

}

int main()
{
#ifndef ONLINE_JUDGE    
   freopen("sgu131.in","r",stdin);
   freopen("sgu131.out","w",stdout);
#endif  

   std::cin >> n >> m;

   full = (1<<m) - 1;   

   f[1][0] = 1; 
   for(int i = 1 ; i <= n ; i++)
   {
      row = i;
      dfs(1 , 0 , 0 , 0 , 0);
      row = 0;
   }

   std::cout << f[n + 1][0];    

#ifndef ONLINE_JUDGE
   fclose(stdin);
   fclose(stdout); 
#endif      
   return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值