首页 > 其他 > 详细

poj1185 [NOI2001]炮兵阵地

时间:2017-12-23 13:43:54      阅读:183      评论:0      收藏:0      [点我收藏+]

http://poj.org/problem?id=1185

 

三维装压dp,压缩上一行状态与本行状态,枚举上两行状态转移

第一维可以滚掉,实际复杂度只枚举符合情况的情况,每行状态不会超过60并非$2^M$,证明参见组合数

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

const int maxnm = 1001;
const int maxn = 11;
int n,m;
char a[maxn];
int cant[maxn*10];
int map[101][11];
bool check(int x,int i) {
    if(x&cant[i])return false;
    if(x&(x<<1)||x&(x<<2))return false;
    return true;
}
int dp[2][1<<maxn][1<<maxn];
int num[1<<maxn];
int main( ) {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)  {
        scanf("%s",a) ;
        for(int j=0;j<m;++j)
            if(a[j]==H)
            cant[i]|=(1<<j);
    }
    int po=(1<<m)-1;
    for(int k,i=1;i<=po;++i) {
        if(!check(i,0))continue;
        k=i;while(k) {
            num[i]+=(k&1);
            k>>=1;
        }
    }
    int ans=-1;
    for(int i=1;i<=n;++i) {
        for(int j=1;j<=po;++j) {
            if(!check(j,i))continue;
            for(int k=1;k<=po;++k) {
                if(!check(k,i-1)||(k&j)) continue;
                for(int p=1;p<=po;++p) {
                    if(!check(p,i-2)||(p&j)||(k&p)) continue;
                    dp[i&1][k][j]=std::max(dp[i&1][k][j],dp[(i&1)^1][p][k]+num[j]);
                }
                if(i==n)ans=std::max(ans,dp[n&1][k][j]);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

 

poj1185 [NOI2001]炮兵阵地

原文:http://www.cnblogs.com/sssy/p/8092748.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!