[P2704][NOI2001]炮兵阵地 (状态压缩)

最近抄状压的代码……

然后盯上了这个题目

调试了一个晚上,终于A了

但是是对着宝典打的,我依然不懂状态压缩

那么下一步先把装压放一放,学一下树形DP吧

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<cstring>
#include<string>
using namespace std;
int n,m,s[110][150];
int f[110][150][150];
int num[110][150];
bool map[1100][1100];
int getnum(int x)
{
    int t=0;
    while(x>0){
        x=x&(x-1);
        t++;
    }
    return t;
}
void dp(){
    s[0][0]=1;
    int s1,s2,m=1;
    for(int i=1;i<=n;i++,m=m^1)
    for(int a=1;a<=s[i-1][0];a++){
        s1=s[i-1][a];
        for(int b=1;b<=s[i][0];b++)
        if(map[s1][s[i][b]]){
            s2=s[i][b];
            if(i==1) f[m][a][b]=max(f[m][a][b],num[i][b]);
            else{
                for(int c=1;c<=s[i-2][0];c++)
                if(map[s[i-2][c]][s1] && map[s[i-2][c]][s2])
                f[m][a][b]=max(f[m][a][b],f[m^1][c][a]+num[i][b]);
            }
        }
    }
    int ans=0;
    m=m^1;
    for(int a=1;a<=s[n-1][0];a++)
    for(int b=1;b<=s[n][0];b++)
    ans=max(ans,f[m][a][b]);
    cout<<ans;
}
int main()
{
    int q;cin>>n>>m;
    string tmp;
    for(int i=1;i<=n;i++)
    {
        cin>>tmp;
        q=0;
        for(int j=0;j<tmp.size();j++){
            if(tmp[j]=='P') q=(q<<1);
            else q=(q<<1)|1;
        }
        for(int j=0;j<(1<<m);j++){
            if((j<<1)&j || (j<<2)&j || (j>>1)&j || (j>>2)&j) continue;
            if(q&j) continue;
            ++s[i][0];
            s[i][s[i][0]]=j;
            num[i][s[i][0]]=getnum(j);
        }
    }
    for(int i=0;i<=(1<<m);i++){
        for(int j=0;j<=(1<<m);j++)
        if(!(i&j)) map[i][j]=true;
    }
    dp();
    return 0;
}

 

posted @ 2018-10-09 20:17  lincold  阅读(196)  评论(0编辑  收藏  举报