zoukankan      html  css  js  c++  java
  • SGU 132. Another Chocolate Maniac 状压dp 难度:1

    132. Another Chocolate Maniac

    time limit per test: 0.25 sec. 
    memory limit per test: 4096 KB

     

    Bob really LOVES chocolate. He thinks he never gets enough. Imagine his joy when his parents told him that they would buy him many rectangular chocolate pieces for his birthday. A piece of chocolate is a 2x1 or1x2 rectangle. Bob's parents also bought him a nice birthday cake, which can be imagined as a matrix having M rows and N columns. Some positions on the cake are occupied by candles, the others are empty. Bob's parents asked their son to place as many chocolate pieces as he can on the empty squares on the cake, in such a manner that no two chocolate pieces overlap. However, he would like to keep the chocolate pieces to himself. That's why, he wants to place only a minimal amount of them on the cake and keep the rest. In order not to make Mon and Dad suspicious, Bob wants to place the chocolate pieces in such a way, that no other piece may be placed on the cake (that is, there won't exist any two adjacent empty squares). Find the minimal number of pieces which need to be placed on the cake, so that they do not overlap and no extra piece may be added.

     

    Input

    The first line of the input contains 2 integers: M (1<=M<=70) and N (1<=N<=7). Next, M lines will follow, each of them containing N characters, describing the cake. The character on row and column of the cake may be either a '*' (ASCII code 42), representing a candle, or a '.' (ASCII code 46), representing an empty square.

     

    Output

    You should output one integer: the minimal amount of pieces of chocolate which need to be placed on the cake.

     

    Sample Input

    5 5
    .*..*
    *....
    ..**.
    **.*.
    .**..
    

    Sample Output

    4
    简单的状态压缩,注意不填充这个格子的时候,可以填充左边的两个,下和右下,下和左下即可,然后就是如果恰有一对上下都没有填充,可以试试能否填充下和下下
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define bin(bit)  (1<<(bit))
    #define spb(x,bit) ((x)&(1<<(bit)))
    const int inf=0x3f3f3f3f;
    char maz[75][10];
    int dp[2][1<<8][1<<8];
    
    int init[75];
    int n,m;
    int row,nrow,len;
    int inver(int ind){//初始状态转成数字
        int ans=0;
        int base=1;
        for(int i=0;i<m;i++){
            if(maz[ind][i]=='*'){
                ans+=base;
            }
            base<<=1;
        }
        return ans;
    }
    bool contain(int nowline,int nxtline,int nnxtline){//如果恰好该状态有格子在某个格和下一个格都没填充,检查能否填充下下格,当然,下下格状态就是下下行对应的初始状态
        int base=1;
        row=nxtline;nrow =nnxtline;len=0;
        for(int i=0;i<m;i++){
            if((nowline&base)==0&&(nxtline&base)==0){
                if((nnxtline&base)!=0)return false;
                else {nrow|=base;row|=base;len++;}
            }
            base<<=1;
        }
        return true;
    }
    bool judge(int nowline,int nxtline){//判断这一行相对下一行是否都符合规范(没有格不合题意)
        for(int i=0;i<m;i++){
            if(spb(nowline,i)==0){
                if(spb(nxtline,i)==0){return false;}
                if(i<m-1&&spb(nowline,i+1)==0)return false;
            }
        }
        return true;
    }
    bool judge(int nowline){//判断这一行是否符合规范
        for(int i=0;i<m;i++){
            if(spb(nowline,i)==0){
                if(i<m-1&&spb(nowline,i+1)==0)return false;
            }
        }
        return true;
    }
    void update(int cnt,int stj,int stk){//用这个状态更新同行的其它状态
        for(int i=0;i<m;i++){
            if(spb(stj,i)==0){
    /*
    TT
    */
                if(i<m-1&&spb(stj,i+1)==0){
                    dp[cnt][stj|bin(i+1)|bin(i)][stk]=min( dp[cnt][stj|bin(i+1)|bin(i)][stk],dp[cnt][stj][stk]+1);
                }
    
    /*
    
    ATT
    */
                if(i<m-2&&spb(stj,i+2)==0&&spb(stj,i+1)==0){
                    dp[cnt][stj|bin(i+2)|bin(i+1)][stk]=min( dp[cnt][stj|bin(i+2)|bin(i+1)][stk],dp[cnt][stj][stk]+1);
                }
    /*
    T
    T
    */
                if(spb(stk,i)==0){
                    dp[cnt][stj|bin(i)][stk|bin(i)]=min( dp[cnt][stj|bin(i)][stk|bin(i)],dp[cnt][stj][stk]+1);
                }
    /*
    A
    TT
    */
                if(i<m-1&&spb(stk,i+1)==0&&spb(stk,i)==0){
                    dp[cnt][stj][stk|bin(i+1)|bin(i)]=min( dp[cnt][stj][stk|bin(i+1)|bin(i)],dp[cnt][stj][stk]+1);
                }
    /*
     A
    TT
    */
                if(i&&spb(stk,i)==0&&spb(stk,i-1)==0){
                    dp[cnt][stj][stk|bin(i)|bin(i-1)]=min( dp[cnt][stj][stk|bin(i)|bin(i-1)],dp[cnt][stj][stk]+1);
                }
            }
        }
    }
    int main(){
        memset(dp[0],0x3f,sizeof(dp[0]));
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++){//初始化
            scanf("%s",maz[i]);
            init[i]=inver(i);
        }
        dp[0][bin(m)-1][init[0]]=0;
        init[n]=0;
        init [n+1]=0;
        int cnt=0;
    
        for(int i=0;i<=n;i++){
            memset(dp[cnt^1],0x3f,sizeof(dp[0]));
             for(int j=0;j<bin(m);j++){//行内dp
                for(int k=0;k<bin(m);k++){
                    if(dp[cnt][j][k]!=inf){
                        update(cnt,j,k);
                    }
                }
            }
           // printdp(i,true);
            if(i==n)continue;//如果恰好到了最后一行了,就不需要行间转移
            for(int j=0;j<bin(m);j++){//行间转移
                if(!judge(j))continue;
                for(int k=0;k<bin(m);k++){
                    if(dp[cnt][j][k]==inf)continue;
                    if(judge(j,k)){//如果已经满足题意
                        dp[cnt^1][k][init[i+1]]=min(dp[cnt^1][k][init[i+1]],dp[cnt][j][k]);
                    }
                    else if(contain(j,k,init[i+1])){//否则试试染下下
                        dp[cnt^1][row][nrow]=min(dp[cnt^1][row][nrow],dp[cnt][j][k]+len);
                    }
                }
            }
          //  printdp(i,false);
            cnt^=1;
        }
        int ans=inf;
        for(int j=0;j<bin(m);j++){
            if(!judge(j))continue;
            ans=min(ans,dp[cnt][j][0]);
        }
        printf("%d
    ",ans);
        return 0;
    }
      
    

      

  • 相关阅读:
    Linux 学习 step by step (1)
    ubuntu server nginx 安装与配置
    ubuntu server samba服务器配置
    iOS app集成支付宝支付流程及后台php订单签名处理
    mac 连接windows 共享内容
    linux 文件查找,which,whereis,locate,find
    ubuntu server vsftpd 虚拟用户及目录
    ubuntu server 安装 mantis bug tracker 中文配置
    ubuntu server vsftpd 匿名用户上传下载及目录设置
    linux 用户管理,用户权限管理,用户组管理
  • 原文地址:https://www.cnblogs.com/xuesu/p/4026319.html
Copyright © 2011-2022 走看看