POJ 2411 Mondriaan's Dream:网格密铺类 状压dp

题目链接:http://poj.org/problem?id=2411

题意:

  给你一个n*m的网格 (1<=n,m<=11) ,往里面铺1*2或2*1的砖块,问你铺完这个网格有多少种不同的方法。

 

题解:

  表示状态:

    dp[state][i] = num of ways at ith row

    (1)当前铺到了第i行

    (2)在铺第i行之前,第i行已经被占的格子状态为state

  如何转移:

    对于当前第i行的第j列处,有三种情况:

    (1)竖着铺。i+1行的第j个位置会被占,在这一行占用了一个宽度,接下来该在第j+1列铺。

    (2)横着铺。对i+1行没有影响,在这一行占用了两个宽度,接下来该在j+2列铺。

    (3)已经被占。只能不铺,对i+1行没有影响,接下来该在第j+1列铺。

    所以在求dp之前先暴搜出在一行上的每个状态state铺完之后下一行的状态,存到vector中。

    转移:枚举每一行i,当前行的state,以及当前state能够转移的状态nex。

      dp[nex][i+1] += dp[state][i]

 

AC Code:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <vector>
 5 #define MAX_N 15
 6 #define MAX_S (1<<12)
 7 
 8 using namespace std;
 9 
10 int n,m;
11 long long dp[MAX_S][MAX_N];
12 vector<int> shift[MAX_S];
13 
14 void dfs(int col,int state,int nex)
15 {
16     if(col==m)
17     {
18         shift[state].push_back(nex);
19         return;
20     }
21     if((state>>col)&1)
22     {
23         dfs(col+1,state,nex);
24         return;
25     }
26     dfs(col+1,state,nex|(1<<col));
27     if(col+1<m && !((state>>(col+1))&1)) dfs(col+2,state,nex);
28 }
29 
30 int main()
31 {
32     while(cin>>n>>m)
33     {
34         if(n==0 && m==0) break;
35         for(int state=0;state<(1<<m);state++)
36         {
37             shift[state].clear();
38         }
39         for(int state=0;state<(1<<m);state++)
40         {
41             dfs(0,state,0);
42         }
43         memset(dp,0,sizeof(dp));
44         dp[0][0]=1;
45         for(int i=0;i<n;i++)
46         {
47             for(int state=0;state<(1<<m);state++)
48             {
49                 if(dp[state][i])
50                 {
51                     for(int j=0;j<shift[state].size();j++)
52                     {
53                         int nex=shift[state][j];
54                         dp[nex][i+1]+=dp[state][i];
55                     }
56                 }
57             }
58         }
59         cout<<dp[0][n]<<endl;
60     }
61 }

 

posted @ 2017-08-16 01:50  Leohh  阅读(331)  评论(0编辑  收藏  举报