luogu P2704 [NOI2001]炮兵阵地

luogu P2704 [NOI2001]炮兵阵地_第1张图片

analysis

首先这是一道状压DP,其次就是方程的设计
f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]是当前行状态为k,前一行为j,前两行为i??这是我最初的想法,但是没有带入列这个参数,且空间开销为 2048 3 b {2048}^{3}b 20483b,所以不行
f [ i ] [ S ] [ K ] f[i][S][K] f[i][S][K]为第i行状态为K,前一行状态为S,这样的话
f [ i ] [ S ] [ K ] = m a x ( f [ i − 1 ] [ L ] [ S ] + n u m [ K ] , f [ i ] [ S ] [ K ] ) , L 是 S 的 前 一 行 f[i][S][K]=max(f[i-1][L][S]+num[K],f[i][S][K]),L是S的前一行 f[i][S][K]=max(f[i1][L][S]+num[K],f[i][S][K]),LS
这时虽然方程写出来了,但是很多oler都会为其正确性而担忧
对于这个问题,我想引用Q大佬的一句话:
在这里插入图片描述
于是就开心的递推了
注意不要把条件写漏了,这把我卡了一下午

code

#include
using namespace std;
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define anti_loop(i,start,end) for(register int i=start;i>=end;--i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define ll long long
int n,m;
const int maxn=110;
const int maxm=10;
const int maxsit=(1<<maxm);
int MAP[maxn];
int sit[maxsit];
int num[maxsit];
int cnt=0;
int f[3][maxsit][maxsit];
template <typename T> void read(T &x)
{
    x=0;char r=getchar();T neg=1;
    while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
    while(r>='0'&&r<='9'){x=(x<<3)+(x<<1)+r-'0';r=getchar();}
    x*=neg;
}
inline int getnum(int i){register int _cnt=0;register int _i=i;while(_i){if((_i&1)==1)++_cnt;_i>>=1;}return _cnt;}
inline void makesit()
{
    loop(i,0,((1<<(m))-1))
    {
        if(((i<<1)&i)==0&&((i<<2)&i)==0)
        {
            sit[cnt]=i;
            num[cnt++]=getnum(i);
        }
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("datain.txt","r",stdin);
    #endif
    read(n);read(m);
    clean(f,0);
    char ra[maxm];
    loop(i,1,n)
    {
        scanf("%s",ra);
        int _aa=0;
        loop(j,0,(m-1))
        {
            _aa<<=1;
            if(ra[j]=='H')_aa+=1;
        }
        MAP[i]=_aa;
    }//将地图压成数便于后面判断
    makesit();//得到所有合法状态,存在sit和num数组中
    loop(K,0,(cnt-1))
    {
        loop(S,0,(cnt-1))
        {
            f[1][sit[S]][sit[K]]=num[K];
            if((sit[S]&sit[K])==0)
                f[2][sit[S]][sit[K]]=num[K]+num[S];
        }
    }
    loop(i,3,n)
    {
        loop(S,0,(cnt-1))
        {
            if((sit[S]&MAP[i-1])!=0)continue;//if on the hill
            loop(K,0,(cnt-1))
            {
                if((sit[K]&sit[S])!=0||(sit[K]&MAP[i])!=0)continue;//if can attacked or on the hill
                loop(L,0,(cnt-1))
                {
                    if((sit[L]&MAP[i-2])!=0||(sit[L]&sit[S])!=0||(sit[L]&sit[K])!=0)continue;//if L can attack S or K or on the hill
                    f[i%3][sit[S]][sit[K]]=max(f[(i-1)%3][sit[L]][sit[S]]+num[K],f[i%3][sit[S]][sit[K]]);
                }
            }
        }
    }
    int res=0;
    loop(i,0,(cnt-1))
    {
        loop(j,0,(cnt-1))
        {
            if((sit[i]&sit[j])!=0)continue;
            res=max(res,f[n%3][sit[i]][sit[j]]);
        }
    }
    printf("%d",res);
    return 0;
}

你可能感兴趣的:(动态规划)