码迷,mamicode.com
首页 > 其他好文 > 详细

poj1185 [NOI2001]炮兵阵地

时间:2017-12-23 14:27:23      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:include   bool   ring   炮兵阵地   style   超过   noi2001   组合数   noi   

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]炮兵阵地

标签:include   bool   ring   炮兵阵地   style   超过   noi2001   组合数   noi   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!