B - 炮兵阵地 POJ - 状压DP

  • B - 炮兵阵地

  •  POJ - 1185
  • 对于原始的矩阵,我们用0来表示可以放置炮兵,即对应图中的P,这样每一行都有一个可以放置炮兵的状态,存到row[N]中,用来check该行的状态是否合法。
  • 由于当前行和前两行有关系,所以得用3维矩阵来保存一个状态下最多的炮兵个数,用dp[i][curst][prest]表示当前第i行状态对curst,前一行状态为prest的最大炮兵数。
  • 转移方程为dp[i][curst][prest]=max{dp[i-1][prest][preprest]},这样求到最后一行之后,答案就是最后一行所有状态中最大的那个。程序初始化的时候需要对第一行
  • 进行预处理,设置dp[0][st][0]=st合法&st中1的个数。这样进行下面的计算的时候,由于0状态肯定是和所有状态兼容的,所以就不会影响计算结果。
  • #include<iostream>
    #include<stdio.h>
    using namespace std;
    #define maxn 111
    #define judge(a,b) a&b
    int row[maxn],m,n;
    int legal[maxn];
    int dp[maxn][maxn][maxn];
    int num[maxn],cnt;
    char str[15];
    int cal(int x)
    {
        int rng=0;
        while(x)
        {
            x&=(x-1);
            rng++;
        }
        return rng;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; i++)
        {
            scanf("%s",str);
            for(int j=0; j<m; j++)
            {
                if(str[j]=='H')
                    row[i]+=(1<<j);
            }
        }
        for(int i=0; i<(1<<m); i++)
        {
            if(judge(i,i<<1)||judge(i,i<<2))continue;
            num[cnt]=cal(i);
            legal[cnt++]=i;
        }
        for(int i=0; i<cnt; i++)
        {
            if(judge(legal[i],row[0]))continue;
            dp[0][i][0]=num[i];
        }
        for(int r=1; r<n; r++)
            for(int i=0; i<cnt; i++)
            {
                if(judge(legal[i],row[r]))continue;
                for(int j=0; j<cnt; j++)
                {
                    if(judge(legal[j],row[r-1]))continue;
                    if(judge(legal[i],legal[j]))continue;
                    for(int k=0; k<cnt; k++)
                    {
                        if(judge(legal[k],row[r-2]))continue;
                        if(judge(legal[i],legal[k]))continue;
                        if(judge(legal[j],legal[k]))continue;
                        dp[r][i][j]=max(dp[r][i][j],dp[r-1][j][k]+num[i]);
                    }
                }
            }
        int ans=0;
        for(int i=0; i<cnt; i++)
            for(int j=0; j<cnt; j++)
                ans=max(ans,dp[n-1][i][j]);
        printf("%d\n",ans);
        return 0;
    }

猜你喜欢

转载自blog.csdn.net/BePosit/article/details/83067739
今日推荐