2018.09.08【POJ1185】炮兵阵地(状压DP)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/82533848

传送门


解析:

经典状压DP

由于 m 只有10,显然可以考虑状压 D P

而又有不能挨得太近的限制,显然我们可以直接预处理出可能存在的方案总数。

最后就是转移,首先合法状况才能转移,代码中用了checksol和checkcannon两个函数实现。

最后特殊处理一下一二行就行了。


代码:

#include<iostream>
#include<cstdio>
#include<cctype>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline
ll getint(){
    re ll num=0;
    re char c;
    while(!isdigit(c=gc()));
    while(isdigit(c))num=(num<<1)+(num<<3)+(c^48),c=gc();
    return num;
}

inline
void outint(ll a){
    static char ch[23];
    if(a==0)pc('0');
    while(a)ch[++ch[0]]=(a-a/10*10)^48,a/=10;
    while(ch[0])pc(ch[ch[0]--]);
}

inline
bool checklegal(int j){
    if((j&(j<<1))||(j&(j<<2)))return false;
    return true;
}
inline int lowbit(int k){return k&-k;}
inline
int cntbit(int k){
    int cnt=0;
    while(k)++cnt,k-=lowbit(k);
    return cnt;
}

int f[101][61][61];
int g[101];
int sta[61],tot;
int num[61];
int n,m;

inline
bool checksol(int i,int j){
    return !(sta[i]&g[j]);
}

inline
bool checkcannon(int i,int j){
    return !(sta[i]&sta[j]);
}

int main(){
    n=getint();
    m=getint();
    for(int re i=0;i<(1<<m);++i){
        if(checklegal(i))sta[++tot]=i,num[tot]=cntbit(i);
    }
    for(int re i=1;i<=n;++i){
        string s;
        cin>>s;
        for(int re j=0;j<m;++j){
            if(s[j]=='H')g[i]|=(1<<j);
        }
    }
    for(int re i=1;i<=tot;++i){
        if(checksol(i,1))
        f[1][i][1]=num[i];
    }
    for(int re i=1;i<=tot;++i){
        if(checksol(i,1))
        for(int re j=1;j<=tot;++j){
            if(checksol(j,2)&&checkcannon(i,j))
            f[2][j][i]=f[1][i][1]+num[j];
        }
    }
    for(int re i=3;i<=n;++i){
        for(int re j=1;j<=tot;++j){
            if(checksol(j,i))
            for(int re k=1;k<=tot;++k){
                if(checksol(k,i-1)&&checkcannon(k,j))
                for(int re t=1;t<=tot;++t){
                    if(checksol(t,i-2)&&checkcannon(k,t)&&checkcannon(t,j))
                    f[i][j][k]=max(f[i][j][k],f[i-1][k][t]+num[j]);
                }
            }
        }
    }
    int maxn=0;
    for(int re i=1;i<=tot;++i)
    for(int re j=1;j<=tot;++j)
    maxn=max(maxn,f[n][i][j]);
    cout<<maxn;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/82533848