zoukankan      html  css  js  c++  java
  • SGU 132 Another Chocolate Maniac 状态压缩DP

    感觉不是很好写的一道状态压缩。

    dp[i][j][k]表示第 i 行状态为k,第i - 1行状态为 j,具体细节见代码。

    内存卡的很死,要用滚动数组。

    还有一个比较坑爹的地方是它在输入蛋糕的时候中间可能会出现空行,一开始我用getchar()读,连第一组数据都过不去,后来改成scanf( "%s", str )才过……错了好多次。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <algorithm>
      5 
      6 using namespace std;
      7 
      8 const int MAXN = 520;
      9 const int INF = 1 << 20;
     10 
     11 int M, N, all;
     12 int G[100];
     13 int dp[2][MAXN][MAXN];
     14 int TwoPow[MAXN];
     15 int initJ, initK;
     16 int cur, pre;
     17 char str[10];
     18 
     19 void init()
     20 {
     21     memset( G, 0, sizeof(G) );
     22     for ( int i = 1; i <= M; ++i )
     23     {
     24         scanf( "%s", str );
     25         for ( int j = 0; j < N; ++j )
     26         {
     27             if ( str[j] == '*' )
     28                 G[i] |= ( 1 << j );
     29         }
     30         //printf( "G[%d]=%d
    ", i, G[i] );
     31     }
     32 
     33     TwoPow[0] = 1;
     34     for ( int i = 1; i <= N; ++i )
     35         TwoPow[i] = ( TwoPow[i - 1] << 1 );
     36 
     37     all = ( 1 << N ) - 1;
     38     return;
     39 }
     40 
     41 //c:当前列, j:当前行的上两行状态, k:当前行的上一行状态
     42 //State:当前行状态, cnt:当前摆放巧克力个数
     43 void DFS( int c, int j, int k, int State, int cnt )
     44 {
     45     //当前行的上两行中出现了2*1的空格
     46     if ( c > 0 && ( ( j & TwoPow[c-1] ) == 0 ) && ( ( k & TwoPow[c-1] )==0 ) )
     47         return;
     48 
     49     //当前行的上一行中出现了1*2的空格
     50     if ( c > 1 && ( ( k & TwoPow[c-1] ) == 0 ) && ( ( k & TwoPow[c-2] )==0 ) )
     51         return;
     52 
     53     if ( c == N )   //当前行摆放完成,状态转移
     54     {
     55         dp[cur][k][State] = min( dp[cur][k][State], dp[pre][initJ][initK] + cnt );
     56         //printf("dp[%d][%d][%d] = %d
    ", cur, k, State, dp[cur][k][State] );
     57         return;
     58     }
     59 
     60     DFS( c + 1, j, k, State, cnt );
     61 
     62     //当前行的上一行放2*1的巧克力并影响当前行的状态
     63     if ( ( ( k & TwoPow[c] ) == 0 ) && ( ( State & TwoPow[c] ) == 0 ) )
     64         DFS( c + 1, j, k | TwoPow[c], State | TwoPow[c], cnt + 1 );
     65 
     66     //当前行的上一行放1*2的巧克力
     67     if ( c + 1 < N && ( ( k & TwoPow[c] ) == 0 ) && ( ( k & TwoPow[c + 1] ) == 0 ) )
     68         DFS( c + 1, j, k | TwoPow[c] | TwoPow[c + 1] , State, cnt + 1 );
     69 
     70     return;
     71 }
     72 
     73 void DP()
     74 {
     75     pre = 0;
     76     cur = 1;
     77 
     78     for ( int j = 0; j <= all; ++j )
     79         for ( int k = 0; k <= all; ++k )
     80             dp[0][j][k] = INF;
     81     dp[0][ all ][ G[1] ] = 0;
     82     //printf("**dp[0][%d][%d] = %d
    ", all, G[1], dp[0][all][G[1]] );
     83 
     84     for ( int i = 1; i <= M; ++i )
     85     {
     86         for ( int j = 0; j <= all; ++j )
     87             for ( int k = 0; k <= all; ++k )
     88                 dp[cur][j][k] = INF;
     89 
     90         for ( int j = 0; j <= all; ++j )
     91             for ( int k = 0; k <= all; ++k )
     92             {
     93                 if ( dp[pre][j][k] != INF )
     94                 {
     95                     initJ = j, initK = k;
     96                     DFS( 0, j, k, G[i + 1], 0 );
     97                 }
     98             }
     99 
    100         pre ^= 1;
    101         cur ^= 1;
    102     }
    103     return;
    104 }
    105 
    106 int main()
    107 {
    108     while ( scanf( "%d%d", &M, &N ) == 2 )
    109     {
    110         init();
    111         DP();
    112 
    113         int ans = INF;
    114         for ( int i = 0; i <= all; ++i )
    115             ans = min( ans, dp[pre][i][0] );
    116         printf( "%d
    ", ans );
    117     }
    118     return 0;
    119 }
  • 相关阅读:
    gsm at 指令
    wm8976 codec
    【Gym 100971J】Robots at Warehouse
    【XDU1144】合并模板
    腾讯云CentOS7安装LNMP+wordpress
    【USACO1.1】Broken Necklace
    【校赛小分队之我们有个女生】训练赛6
    【计导作业】——商品记录
    C 文件读写2
    C 文件读写1
  • 原文地址:https://www.cnblogs.com/GBRgbr/p/3217333.html
Copyright © 2011-2022 走看看