POJ_1185_状态压缩dp

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

 

一次考虑两行,比一行略为复杂。sta保存每种状态炮兵位置,sum保存每种状态当行炮兵总数,a保存地形,dp[i][j][k]表示到第i行当前行j状态上一行k状态的最大炮兵数。

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
//int main()
//{
//    int num = 0;
//    for(int i = 0;i <= (1<<10);i++)
//    {
//        if(i & (i<<2) || i & (i<<1))  continue;
//        num++;
//    }
//    printf("%d",num);
//}

int dp[105][65][65],a[105] = {0},n,m,sta[65],sum[65] = {0};

int main()
{
    memset(dp,-1,sizeof(dp));
    scanf("%d%d",&n,&m);
    getchar();
    if(n == 0 && m == 0)
    {
        printf("0\n");
        return 0;
    }
    for(int i = 0;i < n;i++)
    {
        char temp[15];
        gets(temp);
        for(int j = 0;j < m;j++)
        {
            if(temp[j] == 'H')  a[i] |= (1<<j);
        }
    }
//    for(int i = 0;i < n;i++)    printf("%d\n",a[i]);
    int cnt = 0;
    for(int i = 0;i < (1<<m);i++)
    {
        if(i & (i<<2))  continue;
        if(i & (i<<1))  continue;
        sta[cnt] = i;
        int temp = i;
        while(temp)
        {
            sum[cnt] += temp%2;
            temp /= 2;
        }
        cnt++;
    }
//    for(int i = 0;i < cnt;i++)    printf("%d %d\n",sta[i],sum[i]);
    for(int i = 0;i < cnt;i++)
    {
        if(a[0] & sta[i])   continue;
        dp[0][i][0] = sum[i];
    }
//    for(int i = 0;i < cnt;i++)    printf("%d\n",dp[0][i][0]);
    for(int i = 0;i < cnt;i++)
    {
        if(a[1] & sta[i])   continue;
        for(int j = 0;j < cnt;j++)
        {
            if(sta[i] & sta[j]) continue;
            dp[1][i][j] = max(dp[1][i][j],dp[0][j][0]+sum[i]);
        }
    }
    for(int i = 2;i < n;i++)
    {
        for(int j = 0;j < cnt;j++)
        {
            if(a[i] & sta[j])   continue;
            for(int k = 0;k < cnt;k++)
            {
                if(sta[j] & sta[k])   continue;
                for(int l = 0;l < cnt;l++)
                {
                    if(sta[j] & sta[l]) continue;
                    if(dp[i-1][k][l] == -1) continue;
                    dp[i][j][k] = max(dp[i][j][k],dp[i-1][k][l]+sum[j]);
                }
            }
        }
    }
//    for(int i = 0;i < cnt;i++)
//    {
//        for(int j = 0;j < cnt;j++)  printf("%d ",dp[n-1][i][j]);
//        printf("\n");
//    }
    int ans = -1;
    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;
}

 

posted @ 2016-09-27 21:17  zzzzzzzzhu  阅读(143)  评论(0编辑  收藏  举报