poj 1185 狀態壓縮DP

思路:首先做個預處理,把每一行可以放的狀態存起來,以後就可以只看這麼多狀態而不是for全看一遍了。

之後,因爲放一個可以影響四個方向2格,所以第i行的狀態和i-1行i-2行有關係的,通過之前的狀態來推,狀態轉移方程可以寫爲:

dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+f[i][j])

這裏i代表第i行,j爲第i行的狀態,k爲第i-1行狀態,l爲i-2行狀態,f[i][j]表示第i行在j狀態下放的個數。

記得前兩行特殊處理下。

這裏直接開數組會MLE,所以用滾動數組來。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;
char a[111][15];
int f[111][1025];
int dp[3][1025][1025];
int m,n;
vector<int>g[111];
void pre()
{
    int l=(1<<m);
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<l;j++)
        {
            int cnt=-1;
            int r=j;
            bool flag=0;
            int num=0;
            for(int k=0;k<=m;k++)
            {
                if(r%2)
                {
                    if(cnt!=-1&&cnt<2)
                    {
                        flag=1;
                        break;
                    }
                    if(a[i][k]=='H')
                    {
                        flag=1;
                        break;
                    }
                    num++;
                    cnt=0;
                }
                else if(cnt!=-1)cnt++;
                r/=2;
            }
            if(flag==0)
            {
                g[i].push_back(j);
                f[i][j]=num;
            }
        }
    }
}
void solve()
{
    if(n==1)
    {
        int ans=0;
        for(int i=0;i<g[0].size();i++)ans=max(ans,f[0][g[0][i]]);
        printf("%d\n",ans);
    }
    else
    {
        int ans=0;
        memset(dp,0,sizeof(dp));
        int x=g[0].size();
        int y=g[1].size();
        int z;
        for(int i=0;i<x;i++)
        {
            for(int j=0;j<y;j++)
            {
                if((g[0][i]&g[1][j])==0)
                {
                    dp[0][g[1][j]][g[0][i]]=max(dp[0][g[1][j]][g[0][i]],f[0][g[0][i]]+f[1][g[1][j]]);
                    ans=max(ans,dp[0][g[1][j]][g[0][i]]);
                }
            }
        }
        for(int i=2;i<n;i++)
        {
            x=g[i].size();
            y=g[i-1].size();
            z=g[i-2].size();
            for(int j=0;j<x;j++)
            {
                for(int k=0;k<y;k++)
                {
                    if(g[i][j]&g[i-1][k])continue;
                    for(int l=0;l<z;l++)
                    {
                        if(g[i][j]&g[i-2][l])continue;
                        if(g[i-1][k]&g[i-2][l])continue;
                        dp[1][g[i][j]][g[i-1][k]]=max(dp[1][g[i][j]][g[i-1][k]],dp[0][g[i-1][k]][g[i-2][l]]+f[i][g[i][j]]);
                        ans=max(ans,dp[1][g[i][j]][g[i-1][k]]);
                    }
                }
            }
            for(int j=0;j<x;j++)
            {
                for(int k=0;k<y;k++)
                {
                    dp[0][g[i][j]][g[i-1][k]]=dp[1][g[i][j]][g[i-1][k]];
                }
            }
            memset(dp[1],0,sizeof(dp[1]));
        }
        printf("%d\n",ans);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)scanf("%s",a[i]);
    pre();
    solve();
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章