poj 1185 炮兵阵地 状态压缩dp

思路:定义一个三维数组dp[x][i][j]其中x为now和pre两种状态,now表示当前两行最优解,pre表示出了本行外,前两行的最优解。那么状态转移方程为

dp[now][j][k]=max(dp[now][j][k],dp[pre][k][r]+num[i][j][1])。num[i][j][1]表示第i行的第j个状态的1的个数。转移条件是!(num[i][j][0]&num[i-1][k][0])&&!(num[i][j][0]&num[i-2][r][0])&&!(num[i-1][k][0]&num[i-2][r][0])为真。

#include<iostream>

#include<cstring>

#include<algorithm>

#include<cstdio>

#define Maxn 1010

using namespace std;

int dp[2][Maxn][Maxn],now,pre,num[110][Maxn][2],cnt1,cnt2,cnt3,graphic[110][11],n,m;

void dfs(int u,int j,int f)

{

    int i;

    if(j==m)

    {

        int sum,cc;

        sum=cc=0;

        for(i=m;i>=1;i--)

        {

            sum+=graphic[u][i]*(1<<(m-i));

            if(graphic[u][i])

                cc++;

        }

        if(f<=2)

        {

            if(graphic[u][j])

            {

                if(sum!=1)

                {

                num[u][++cnt1][0]=sum-1;

                num[u][cnt1][1]=cc-1;

                }

            }

            else

            {

                num[u][++cnt1][0]=sum;

                num[u][cnt1][1]=cc;

            }

        }

        else

        {

            if(graphic[u][j])

            {

                if(sum!=1)

                {

                num[u][++cnt1][0]=sum-1;

                num[u][cnt1][1]=cc-1;

                }

                num[u][++cnt1][0]=sum;

                num[u][cnt1][1]=cc;

            }

            else

            {

                num[u][++cnt1][0]=sum;

                num[u][cnt1][1]=cc;

            }

        }

        return ;

    }

    if(f<=2)

    {

        if(graphic[u][j]==1)

        {

            graphic[u][j]=0;

            dfs(u,j+1,f+1);

            graphic[u][j]=1;

        }

        else

            dfs(u,j+1,f+1);

    }

    else

    {

        if(graphic[u][j])

        {

            dfs(u,j+1,1);

            graphic[u][j]=0;

            dfs(u,j+1,f+1);

            graphic[u][j]=1;

        }

        else

            dfs(u,j+1,f+1);

    }

}

void out(int x)

{

    if(x==1||x==0)

    {

        printf("%d",x);

        return ;

    }

    int temp=x%2;

    out(x/2);

    printf("%d",temp);

}

int main()

{

    int i,j,k,r;

    char str[20];

    memset(graphic,0,sizeof(graphic));

    while(scanf("%d%d",&n,&m)!=EOF)

    {

        memset(dp,0,sizeof(dp));

        memset(num,0,sizeof(num));

        memset(graphic,0,sizeof(graphic));

        for(i=1;i<=n;i++)

        {

            scanf("%s",&str);

            for(j=0;j<m;j++)

            {

                if(str[j]=='P')

                    graphic[i][j+1]=1;

                else

                    graphic[i][j+1]=0;

            }

        }

        dfs(1,1,3);

        cnt2=cnt1;

        cnt1=0;

        dfs(2,1,3);

        now=1,pre=0;

        for(i=1;i<=cnt2;i++)

        for(j=1;j<=cnt1;j++)

        {

            if(!(num[1][i][0]&num[2][j][0]))

                dp[now][j][i]=num[1][i][1]+num[2][j][1];

        }

        for(i=3;i<=n;i++)

        {

            cnt3=cnt2,cnt2=cnt1,cnt1=0;

            dfs(i,1,3);

            now=!now,pre=!pre;

            for(j=1;j<=cnt1;j++)

                for(k=1;k<=cnt2;k++)

                for(r=1;r<=cnt3;r++)

                {

                    if(!(num[i][j][0]&num[i-1][k][0])&&!(num[i][j][0]&num[i-2][r][0])&&!(num[i-1][k][0]&num[i-2][r][0]))

                        dp[now][j][k]=max(dp[now][j][k],dp[pre][k][r]+num[i][j][1]);

                }

        }

        int ans=0;

        for(i=1;i<=cnt1;i++)

            for(j=1;j<=cnt2;j++)

            {

                ans=max(ans,dp[now][i][j]);

            }

        printf("%d\n",ans);

    }

    return 0;

}

 

你可能感兴趣的:(poj)