poj 1185 炮兵陣地(狀壓dp)

題目鏈接:

http://poj.org/problem?id=1185

題目大意:

中文題。

範圍:

N <= 100;M <= 10。

思路:

狀壓dp。

還是將炮兵擺放的地方設1,不放的地方設0。

因爲他對炮兵的攻擊範圍做了要求,也就是相鄰的炮兵位置不能小於2。那麼我們就要先篩選出滿足這個硬性條件的狀態。

然後我們可以發現,對於第i行的狀態,與上一行以及上上一行有關。

所以考慮設一個三維dp[i][j][k],代表到第i行時,第i行的狀態爲j,第i-1行的狀態爲k時候的最大的可以擺放的數量。

這樣我們就可以得到轉移方程:dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+num[j]),這裏num[j]表示在第i行的狀態j裏面放了多少個炮兵,也就有多少個1。

代碼:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
int n,m,kk;
int dp[105][110][110],cur[105],state[110],num[110];
bool ok(int x)
{
    if(x&(x<<1))return 0;
    if(x&(x<<2))return 0;
    return 1;
}
void init()
{
    for(int i=0;i<(1<<m);i++)
    {
        if(ok(i)){state[kk++]=i;
        }
    }
}
int cal(int x)   //計算x的狀態下有多少個1;
{
    int ans=0;
    while(x)
    {
        ans++;
        x&=(x-1);
    }
    return ans;
}
bool judge(int x,int y)
{
    return x&y;
}
int main()
{
    char c;
    int i,j,k,l;
    while(~scanf("%d%d",&n,&m))
    {
        kk=0;
        memset(num,0,sizeof(num));
        memset(dp,0,sizeof(dp));
        memset(cur,0,sizeof(cur));
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
        {
            cin>>c;
            if(c=='H')cur[i]+=(1<<(m-j));
        }
        init();
        for(i=0;i<kk;i++)
        {
            num[i]=cal(state[i]);
            if(!judge(cur[1],state[i]))
                {dp[1][i][0]=num[i];    //邊界處理
        }
        }
        for(i=2;i<=n;i++)
        {
            for(j=0;j<kk;j++)
            {
                if(judge(cur[i],state[j]))continue;
                for(k=0;k<kk;k++)
                {
                    if(judge(state[j],state[k]))continue;
                    for(l=0;l<kk;l++)
                    {
                        if(judge(state[k],state[l]))continue;
                        if(judge(state[j],state[l]))continue;
                        dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+num[j]);
                    }
                }
            }
        }
        int ans=0;
            for(j=0;j<kk;j++)
            for(k=0;k<kk;k++)
            ans=max(ans,dp[n][j][k]);
            printf("%d\n",ans);
    }
}


發佈了235 篇原創文章 · 獲贊 4 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章