• 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
  • 相关阅读:
    七个高效的文本编辑习惯(以Vim为例)
    rbx1 package 下载安装过程
    ros机器人开发概述
    ROS BY EXAMPLE 1 -- 环境设置与安装
    除法取模练习(51nod 1119 & 1013 )
    kinect driver install (ubuntu 14.04 & ros-indigo)
    ros问题总结
    200行代码搞定炸金花游戏(PHP版)
    JavaScript方法call,apply,caller,callee,bind的使用详解及区别
    javascript中apply、call和bind的区别
  • 原文地址:https://www.cnblogs.com/allh123/p/3228892.html
Copyright © 2020-2023  润新知