1. 程式人生 > >炮兵陣地 POJ

炮兵陣地 POJ

  • 對於原始的矩陣,我們用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;
    }