POJ 3254 Corn Fields状态压缩DP

下面有别人的题解报告,并且不止这一个状态压缩题的哦····

http://blog.csdn.net/accry/article/details/6607703

下面是我的代码,代码很挫,绝对有很大的优化的空间····

 1 #include <cstdio>
 2 #include <cstring>
 3 int dp[2][(1 << 12) + 2];
 4 //检查一行的奶牛放置情形是否合理
 5 //即是否有相邻的两个1,没有返回true
 6 bool checkHori(int state)
 7 {
 8     if(!(state & (state << 1)) ) return true;
 9     else return false;
10 }
11 
12 //检查竖直方向的奶牛放置情形是否合理
13 //即是否竖直方向有相同的1
14 bool checkVert(int a,int b)
15 {
16     if(!(a&b)) return true;
17     else return false;
18 }
19 
20 //看该位置是否是肥沃的土地
21 //关系式自己推出来
22 bool checkPos(int map,int state)
23 {
24     if( (map| state) == map) return true;
25     else return false ;
26 }
27 
28 //该算法时间复杂度很高,为O(m*2^(2*n))
29 //最坏情况下为O(12*2^24),10^8左右,一定是可以改进的
30 int main()
31 {
32     freopen("in.cpp","r",stdin);
33     int m,n;
34     scanf("%d%d",&m,&n);
35     memset(dp,0,sizeof(dp));
36     dp[0][0] = 1;
37     int x=0;
38     for(int i=1; i<=m; ++i)
39     {
40         int t,tmp=1,map =0; //map用来记录第i行土地的土壤状态
41         for(int d=0; d<n ; ++d)
42         {
43             scanf("%d",&t);
44             map += t*tmp;
45             tmp *=2;
46         }
47         x =1-x;
48         for(int j=0; j< (1 << n); ++j)
49             dp[x][j] = 0;  //滚动数组,用时间换空间
50         for(int j=0; j< (1 << n); ++j)
51         {
52             for(int k=0; k < (1 << n); ++k)
53             {
54                 if( checkHori(k) && checkPos(map,k) && (i == 1 || checkVert(k,j) )  )
55                     dp[x][k] += dp[1-x][j];
56             }
57         }
58     }
59     int ans=0;
60     for(int i=0; i< (1 << n); ++i)
61     {
62         ans += (dp[x][i] % 100000000);
63         ans %= 100000000;
64     }
65     printf("%d
",ans);
66     return 0;
67 }
View Code

通过计算得出,当n = 12时,2^12 = 4096,而一行能成功放置的方法数仅为377,

由此可先预处理,离散化存储,极大地降低复杂度。新的算法的复杂度最坏情况下为12*377*377,大概为10^6的复杂度。

 1 #include <cstdio>
 2 #include <cstring>
 3 int dp[2][400];
 4 int st[400];
 5 //检查一行的奶牛放置情形是否合理
 6 //即是否有相邻的两个1,没有返回true
 7 bool checkHori(int state)
 8 {
 9     if(!(state & (state << 1)) ) return true;
10     else return false;
11 }
12 
13 //检查竖直方向的奶牛放置情形是否合理
14 //即是否竖直方向有相同的1
15 bool checkVert(int a,int b)
16 {
17     if(!(a&b)) return true;
18     else return false;
19 }
20 
21 //看该位置是否是肥沃的土地
22 //关系式自己推出来
23 bool checkPos(int map,int state)
24 {
25     if( (map| state) == map) return true;
26     else return false ;
27 }
28 
29 int  init(int n)
30 {
31     int num=0;
32     for( int i=0; i<(1<<n); ++i )
33     {
34         if(checkHori(i))
35         {
36             st[num++] = i;
37         }
38     }
39     return num;
40 }
41 int main()
42 {
43 //    freopen("in.cpp","r",stdin);
44     int m,n;
45     scanf("%d%d",&m,&n);
46     int num=init(n);
47     memset(dp,0,sizeof(dp));
48     dp[0][0] = 1;
49     int x=0;
50     for(int i=1; i<=m; ++i)
51     {
52         int t,tmp=1,map =0; //map用来记录第i行土地的土壤状态
53         for(int d=0; d<n ; ++d)
54         {
55             scanf("%d",&t);
56             map += t*tmp;
57             tmp *=2;
58         }
59         x =1-x;
60         for(int j=0; j< num; ++j)
61             dp[x][j] = 0;  //滚动数组,用时间换空间
62         for(int j=0; j< num; ++j)
63         {
64             for(int k=0; k < num; ++k)
65             {
66                 if(checkPos(map,st[k]) && (i == 1 || checkVert(st[k],st[j]) )  )
67                     dp[x][k] += dp[1-x][j];
68             }
69         }
70     }
71     int ans=0;
72     for(int i=0; i< num; ++i)
73     {
74         ans += (dp[x][i] % 100000000);
75         ans %= 100000000;
76     }
77     printf("%d
",ans);
78     return 0;
79 }
View Code
原文地址:https://www.cnblogs.com/allh123/p/3228892.html