• POJ 1038 Bugs Integrated, Inc. (状态dp)


    确实是好题。。。看解题报告看了一天半,才大概明白是怎么样一个过程。最让我纠结的是M,N的行列问题。。。。文字描述里的M,N和图片上的M,N不对应。本菜只能无比蛋疼而又晕晕乎乎的看。。。

    -------------------------------以下部分转自大牛chinaeli-----------------------------------------http://hi.baidu.com/chinaeli/blog/item/b932d4b430d60ac636d3ca34.html

    好了,废话说道这里,我来说说我的想法(其实这个方法都是大家用的,我也是效仿别人的方法)
    首先说一下如何用三进制表示状态:


    假设现在考虑(m,i),从而推出(m,i+1)的状态,因此我们需要记录第i列以及第i-1列的状态,用三进制表示的方法就是A(用0表示),B(用1表示),C(用2表示),其中虚线部分为第i+1列(这个图片旋转90度比较好,做图片时粗心了,嘻嘻),C状态中,因为假如第i列不能放,那么自然第i-1列放和不放都无关紧要了,所以用灰色表示。用p(m)表示第m行,第i列和第i-1列的状态,那么整个的放置状态就是p(0)*3^0+p(1)*3^1......p(M-1)*3^(M-1),转成10进制存储。
    状态表示完之后,就要进行状态转移了。


    M位的三进制共有3^M种状态,( 0<M<=10),因此最大有59049种状态,采用滚动数组,只要开一个2*59049大小的二维数组就可以了。将边界条件f[0][3^M-1]=0,其余初始为-1,表示该状态不可到达或者尚未到达。然后从第0行开始考虑,枚举每行的状态( 从0到3^M-1 ) ,用s表示,将10进制数转换成3进制存在一个p数组中,接着需要产生一个新的状态,也就是第i+1列的状态:

    由于下移了一列,第i-1列我们暂不考虑,之前的A状态变成了A',B变成了B',C变成了C’,之前的0和1都变成新状态的0,原来的2状态变成了新状态的1,但是需要考虑的是第i+1列中是否会存在不能放的区域,假如上图的某个问号中某处不能放置东西,那么不论这个状态是0,还是1,都将变成2,将新状态存于q数组中。现在新生成的状态t是在第i+1行不放置任何东西的状态,那么自然f[i+1][t]=f[i][s].

    现在就要进入关键的部分了,用dfs搜索各种摆放的状态。

    假设现在枚举到(m,n),目前状态是s,目前已经摆放了cnt个芯片。


    如果m<M-2,说明还有至少3列的空处,可以摆放A方式的芯片,但是必须满足(m,n),(m,n-1),(m+1,n),(m+1,n-1),(m+2,n),(m+2,n-1)处空白,也就是q[m]==0 && q[m+1]==0&& q[m+2]==0.那么将状态修改为s=s+2*3^m+2*3^(m+1)+2*3^(m+2)。同理进行B方式的摆放,不过在摆放B时,需要考虑到第n-2行,所以要保证p[m]==0,p[m+1]==0。
    当然这一格也可以不摆放。

     

     

     

     

    View Code
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define Max(a,b) (a>b?a:b)
    #define N 59050
    //三进制
    int tri[12]={0,1,3,9,27,81,243,729,2187,6561,19683,59049};
    int map[151][11];
    int dp[2][N];
    //前一状态,当前状态
    int info_pre[11],info_cur[11];
    int n,m,pass;
    //初始化
    void Init()
    {
        memset(map,0,sizeof(map));
        memset(dp,-1,sizeof(dp));
    }
    //转化 十进制
    int switch_ten(int *p)
    {
        int i,ans;
        for(i=1,ans=0;i<=m;i++){
            ans += p[i]*tri[i];
        }
        return ans;
    }
    //转化 三进制
    void switch_tri(int t,int *p)
    {
        int i;
        for(i=1;i<=m;i++){
            p[i] = t%3;
            t/=3;
        }
        return ;
    }
    void dfs(int i,int j,int cnt,int stata)
    {
        int k;
        dp[i%2][stata] = Max(dp[i%2][stata],cnt);
        if(j >= m ) return ;
        if(!info_pre[j] && !info_pre[j+1] && !info_cur[j] && !info_cur[j+1]){
            // 3*2 排列时 
            info_cur[j] = info_cur[j+1] = 2;
            k = switch_ten(info_cur);
            dfs(i,j+2,cnt+1,k);
            info_cur[j]=info_cur[j+1]=0;
        }
        if(j < m-1 && !info_cur[j] && !info_cur[j+1] && !info_cur[j+2]){
            // 2*3 排列时
            info_cur[j] = info_cur[j+1] = info_cur[j+2] = 2;
            k = switch_ten(info_cur);
            dfs(i,j+3,cnt+1,k);
            info_cur[j] = info_cur[j+1] = info_cur[j+2] = 0;
        }
        dfs(i,j+1,cnt,stata);
        return ;
    }
    int main()
    {
    
        int t,k,i,j,l,stata,ans;
        scanf("%d",&t);
        while(t--){    
            Init();
            scanf("%d%d%d",&n,&m,&k);
            while(k--){
                scanf("%d%d",&i,&j);
                map[i][j] = 1;
            }
            for(i=1;i<=m;i++){
                info_pre[i] = map[1][i] + 1;
            }
            stata = switch_ten(info_pre);
            dp[1][stata] = 0;
            for(i=2;i<=n;i++){
    
                for(j=0;j<tri[m+1];j++)dp[i%2][j] = -1;
            
                for(j=0;j<tri[m+1];j++){
                    
                    if(dp[(i+1)%2][j] == -1)continue;
                
                    switch_tri(j,info_pre);
                
                    for(l=1;l<=m;l++){
                        if(map[i][l])
                            info_cur[l] = 2;
                        else info_cur[l] = Max(info_pre[l]-1,0);
                    }
                    pass = dp[(i+1)%2][j];
                    dfs(i,1,pass,switch_ten(info_cur));
                }
            }
            for(i=0,ans=0;i<tri[m+1];i++){
                ans = Max(ans,dp[n%2][i]);
            }
            printf("%d\n",ans);
        
        }
        return 0;
    }

     

     

     

  • 相关阅读:
    Read-Copy Update Implementation For Non-Cache-Coherent Systems
    10 华电内部文档搜索系统 search04
    10 华电内部文档搜索系统 search05
    lucene4
    10 华电内部文档搜索系统 search01
    01 lucene基础 北风网项目培训 Lucene实践课程 索引
    01 lucene基础 北风网项目培训 Lucene实践课程 系统架构
    01 lucene基础 北风网项目培训 Lucene实践课程 Lucene概述
    第五章 大数据平台与技术 第13讲 NoSQL数据库
    第五章 大数据平台与技术 第12讲 大数据处理平台Spark
  • 原文地址:https://www.cnblogs.com/vongang/p/2615322.html
Copyright © 2020-2023  润新知