poj3254

题目大意:给你一个n*m的矩形,里面有些格子可以选取。。在可选取选取格子,要求不能相邻。。求方案数。。

思路:状态压缩dp

       f[i][j]表示第i行状态为J的方案数

      f[i][j] = sigma(f[i - 1][k])  状态k表示的取法与j取的不相邻。且j为合法取法(与给定的不冲突)

   

 1 /*
 2   Time:2013-03-19 23:07:07
 3   State:Accepted
 4 */
 5 #include <iostream>
 6 #include <cstring>
 7 #include <cstdlib>
 8 #include <cstdio>
 9 #include <cmath>
10 #include <string>
11 #include <algorithm>
12 using namespace std;
13 int n, m , map[25] , tot(0), a[1000] , maxnum;
14 int  f[15][1 << 14];
15 void init(){
16      int x;
17      scanf("%d%d", &n ,&m);
18      for (int i = 1;  i <= n; ++i)
19          for (int j = 0; j < m; ++j){
20               scanf("%d",&x);
21               map[i] = map[i] | (x << j);
22          }
23 }
24 
25 void work_opt(int i , int opt){
26      if (i > m){
27          a[++tot] = opt;  
28          return;
29      }
30      work_opt(i + 1, opt);
31      work_opt(i + 2, opt | (1 << i - 1));
32 }
33 
34 void dp(){
35      int opt;
36      work_opt(1,0);
37      f[0][0] = 1;
38      for (int i = 1; i <= n; ++i)
39          for (int j = 1; j <= tot; ++j){
40             opt = map[i] & a[j];
41             if (opt != a[j]) continue;
42             for (int k = 1; k <= tot; ++k)
43                if ((opt & a[k]) == 0) f[i][opt] = (f[i][opt] + f[i-1][a[k]])% 100000000;      
44          } 
45      int  ans = 0;
46     /* for (int i = 1; i <= tot; ++i)
47          printf("a[%d] = %d\n",i , a[i]);
48      for (int i = 1; i <= n; ++i)
49          for (int  j = 1 ; j <= tot; ++j)
50               printf("f[%d][%d] = %d\n", i, a[j], f[i][a[j]]);*/
51      for (int i = 1; i <= tot; ++i)
52          ans = (ans + f[n][a[i]]) % 100000000;
53      printf("%d\n", ans);
54 }
55 
56 int main(){
57     freopen("poj3254.in","r",stdin);    
58     freopen("poj3254.out","w",stdout);
59     init();
60     dp();
61     fclose(stdin); fclose(stdout);
62 }
原文地址:https://www.cnblogs.com/yzcstc/p/2977957.html