状态压缩动态规划——布阵类问题

这三道题目异曲同工,如果不能完成,那么看懂一道题的题解后,自己实现剩余两道应该没有问题

顺便附一个状压dp的视频讲解
点此进入
POJ-3254 Corn Fields

#include<cstdio>
#include<algorithm>
#include<cstring>

const int MOD=100000000,STATE=1<<12,ROW=12+1;

int St[STATE+1],Bare[ROW],dp[ROW][STATE];

int main(){
    int k=0;
    for(int i=0;i<STATE;++i)if(!(i&(i<<1)))St[k++]=i;//每行所有的合法状态
    St[k]=STATE;
    int m,n,t;
    scanf("%d%d",&m,&n);
    for(int i=0;i<m;++i){
        for(int j=0;j<n;++j){
            scanf("%d",&t);Bare[i]=(Bare[i]<<1)|(!t);
        }
    }
    int s=1<<n;
    for(int i=0;St[i]<s;++i)if(!(Bare[0]&St[i]))dp[0][i]=1;
    for(int r=1;r<m;++r){
        for(int i=0;St[i]<s;++i){
            if(!(Bare[r-1]&St[i])){
                for(int ri=0;St[ri]<s;++ri){
                    if(!(Bare[r]&St[ri]) && !(St[i]&St[ri])){
                        dp[r][ri]=(dp[r][ri]+dp[r-1][i])%MOD;
                    }
                }
            }
        }
    }
    int ans=dp[m-1][0];
    for(int i=1;St[i]<s;++i){
        ans=(ans+dp[m-1][i])%MOD;
    }
    printf("%d\n",ans);
    return 0;
}

HDU-4539 排兵布阵

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>

const int STATE=1<<10;
int dp[101][180][180],num[1<<10+1],St[201],marsh[201];

int get_bit1(int x){
    int nx=0;
    while(x){
        if(x%2)nx++;
        x/=2;
    }
    return nx;
}

bool ok(int x,int y){
    if(x & y<<1 || x<<1 & y) return 0; 
    return 1;
}

int main(){
    int m,n,k=0;
    for(int i=0;i<STATE;++i){
        if(!(i&(i<<2)))St[k++]=i;
        num[i]=get_bit1(i);
    }
    St[k]=STATE;
    //std::cout<<k<<"\n";
    while(scanf("%d%d",&n,&m)==2&&n){
        memset(dp,-1,sizeof(dp));
        int t;
        for(int i=0;i<n;++i){
            marsh[i]=0;
            for(int j=0;j<m;++j){
                scanf("%d",&t);marsh[i]=(marsh[i]<<1)|(!t);
            }
        }
        int s=1<<m;
        for(int i=0;St[i]<s;++i){
            if(!(marsh[0]&St[i]))
            for(int j=0;St[j]<s;++j){
                dp[0][i][j]=num[St[i]];
            }
        }

        for(int i=0;St[i]<s;++i){
            if(!(marsh[1]&St[i]))
            for(int j=0;St[j]<s;++j){
                if(ok(St[i],St[j]) && !(marsh[0]&St[j]))
                for(int kk=0;St[kk]<s;++kk){
                    if(dp[0][j][kk]!=-1)dp[1][i][j]=std::max(dp[0][j][kk]+num[St[i]],dp[1][i][j]); 
                }

            }
        }

        for(int r=2;r<n;++r){
            for(int i=0;St[i]<s;++i){
                if(!(St[i]&marsh[r-2])){
                    for(int ri1=0;St[ri1]<s;++ri1){
                        if(!(St[ri1]&marsh[r-1])){
                            for(int ri=0;St[ri]<s;++ri){
                                if(!(St[ri]&marsh[r]) && (!(St[i]&St[ri])) && ok(St[ri1],St[ri]) ){
                                    if(dp[r-1][ri1][i]!=-1)
                                    dp[r][ri][ri1]=std::max(dp[r][ri][ri1],dp[r-1][ri1][i]+num[St[ri]]);
                                }
                            }
                        }
                    }
                }
            }
        }
        int ans=0;
        for(int i=0;St[i]<s;++i)
        {
            for(int j=0;St[j]<s;++j)
            ans = std::max(ans,dp[n-1][i][j]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

POJ-1185 炮兵布阵

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int STATE=1<<11,ROW=101;

inline int get_bit1(int x){
    int nx=0;
    while(x){
        if(x%2)nx++;
        x/=2;
    }
    return nx;
}

int st[101],n,m,marsh[101],dp[ROW][101][101],ST,num[STATE];
char tab[ROW][10+1];

inline void init(){
    for(int i=0;i<n;++i){
        marsh[i]=0;
        for(int j=0;j<m;++j)
            if(tab[i][j]!='P')marsh[i]=(marsh[i]<<1)|1;
            else marsh[i]=marsh[i]<<1;
    }
    memset(dp,-1,sizeof(dp));
    ST=1<<m;
    for(int i=0;st[i]<ST;++i){
        if(!(marsh[0]&st[i]))
        for(int j=0;st[j]<ST;++j){
            dp[0][i][j]=num[st[i]];
        }
    }
}

int dfs(int row,int r1,int r2){
    int &d=dp[row][r1][r2];
    if(row==0||d!=-1){
        return d;
    }
    d=0;
    if(row==1){
        for(int r3=0;st[r3]<ST;++r3){
            if(!(st[r1]&st[r2]) && dp[row-1][r2][r3]!=-1 &&!(marsh[row]&st[r1])){
                d=std::max(d,dfs(row-1,r2,r3)+num[st[r1]]);
            }
        }
        return d;
    }

    if(!(marsh[row-1]&st[r2]) && !(marsh[row]&st[r1])){
        for(int r3=0;st[r3]<ST;++r3){
            if(!(marsh[row-2]&st[r3])){
                if(!(st[r1]&st[r2]) && !(st[r2]&st[r3]) && !(st[r1]&st[r3])){
                    d=std::max(d,dfs(row-1,r2,r3)+num[st[r1]]);
                }
            }
        }
    }
    return d;
}
int main(){
    int k=0;
    for(int i=0;i<STATE;++i){
        if(!((i<<2)&i) && !((i<<1)&i))st[k++]=i;
        num[i]=get_bit1(i);
    }st[k]=STATE;
    while(scanf("%d%d",&n,&m)==2&&n){
        for(int i=0;i<n;++i)scanf("%s",tab[i]);
        init();
        int ans=0;
        for(int i=0;st[i]<ST;++i){
            for(int j=0;st[j]<ST;++j){
                ans=std::max(ans,dfs(n-1,i,j));
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
全部评论

相关推荐

02-01 19:48
门头沟学院 Java
神哥了不得:(非引流)直接暑期吧,没时间日常了,老鱼简历把水印去了,或者换个模板,简历字体大小都不太行,建议换2个高质量的项目,面试应该还会再多一些
点赞 评论 收藏
分享
一天代码十万三:实习东西太少了,而且体现不出你业务,3个月不可能就这点产出吧,建议实习多写点,玩具项目面试官都不感兴趣的
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务