题意:题意:给定一个长宽小于等于11的矩形,问用1×2的小矩形填满,有多少种方法。
思路:经典的状态压缩题目
用2进制表示状态
f[i][opt]表是第i行状态为opt时的方法数
f[i][opt] = sigma(f[i-1][opt1])期中opt1如果当前位上没放,那么opt就必须放一个竖的。。。
答案为sigma(f[n][i])
1 /* 2 STATE:ACCEPTED 3 TIME:2013.3.3 4 */ 5 #include <iostream> 6 #include <cstring> 7 #include <string> 8 #include <cstdlib> 9 #include <cstdio> 10 #include <cmath> 11 #include <algorithm> 12 #include <vector> 13 const int maxm = 12; 14 long long f[15][1 << maxm] , num; 15 int n , m , maxnum , ans ; 16 17 void swap(int &a , int &b){ 18 int c = a; 19 a = b; 20 b = c; 21 } 22 23 void updata(int i , int opt, int pos ){ 24 if (pos == m){ 25 f[i][opt] += num; 26 return; 27 } 28 updata(i , opt , pos + 1); 29 if (pos < m && !(1 << pos - 1 & opt) && !(1 << pos & opt) ) 30 updata( i , opt | (1 << pos - 1) | (1 << pos) , pos + 1); 31 } 32 33 void dp(){ 34 memset(f , 0 , sizeof(f)); 35 num = 1; 36 maxnum = (1 << m) - 1; 37 updata(1 , 0 , 1); 38 for (int i = 2; i <= n; ++i) 39 for (int opt = 0; opt < 1 << m; ++opt){ 40 if (f[i - 1][opt]) num = f[i - 1][opt]; 41 else continue; 42 updata(i , ~ opt & maxnum , 1 ); 43 } 44 printf("%lld\n",f[n][maxnum]); 45 } 46 47 int main(){ 48 freopen("poj2411.in","r",stdin); 49 freopen("poj2411.out","w",stdout); 50 scanf("%d%d",&n , &m); 51 while (n && m){ 52 if (n < m) swap(n , m); 53 dp(); 54 scanf("%d%d",&n ,&m); 55 } 56 }