luogu 2704 炮兵阵地 状压dp

状压的基础题吧

第一次看感觉难上天,后来嘛就。。

套路:先根据自身状态筛出可行状态,再根据地图等其他限制条件筛选适合的状态加入答案

f i,j,k 分别代表 行数,本行状态,上行状态,再累加答案即可

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
using namespace std;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;}
inline int calc(int x){int ans=0;for(;x;x-=x&(-x))ans++;return ans;}
//state 状态的具体集合
//num   状态的答案贡献(1数量) 
int cnt,n,m;
int f[100][64][64],num[64],state[64],g[100];
void dp(){
    int ans=0;
    memset(f,0,sizeof f);
    for(int i=0;i<n;i++)//本行 
    for(int j=0;j<cnt;j++){//本行状态 
        if(g[i]&state[j]) continue;
        if(i==0) f[i][j][0]=num[j];
        else if(i==1){
            for(int k=0;k<cnt;k++){
                if(g[i-1]&state[k]) continue;
                if(state[j]&state[k]) continue;
                f[i][j][k]=max(f[i][j][k],f[i-1][k][0]+num[j]);
            }
        }else{
            for(int k=0;k<cnt;k++){
                if(g[i-1]&state[k]) continue;
                if(state[j]&state[k]) continue;
                for(int p=0;p<cnt;p++){
                    if(g[i-2]&state[p]) continue;
                    if(state[k]&state[p]||state[j]&state[p]) continue;
                    //三行都要兼容
                    f[i][j][k]=max(f[i][j][k],f[i-1][k][p]+num[j]); 
                }
            }
        } 
    }
    for(int j=0;j<cnt;j++)
    for(int k=0;k<cnt;k++)
        ans=max(ans,f[n-1][j][k]);
    printf("%d\n",ans);
}
int main(){
    char s[12];
    int i,j;
    n=read();m=read();
    for(i=0;i<n;i++){
        scanf("%s",s);
        for(j=0;j<m;j++)
        if(s[j]=='H') g[i]+=(1<<(m-1-j));
    }
    int tmp;cnt=0;
    for(int i=0;i<(1<<m);i++){
        tmp=i;
        if(((tmp<<1)&i)|((tmp<<2)&i)) continue;
        state[cnt]=i;
        num[cnt]=calc(i);++cnt;}
    //利用函数计算当前状态中1的数量 
    //cnt代表当前限制条件下合法状态 
    dp();return 0;
}
//先根据自身条件确定状态
//再根据给定地图判断 

 

posted @ 2018-09-07 15:39  ASDIC减除  阅读(108)  评论(0编辑  收藏  举报