andre_joy

导航

poj 1185

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

题意:中文……

mark:经典的状态压缩dp。第一次写,在网上看别人解题报告看了好多,百度一下就有很多。

   推荐一个解释很详细的解题报告http://apps.hi.baidu.com/share/detail/14572384

   wa了好多次。特别是match函数那,有很多a,b为0的时候的临界情况。

   ps:别人的代码不一定是正确的,我找了一篇ac代码,然后比对数据,结果发现他的数据不对。囧……

代码:

#include <stdio.h>
#include <string.h>
#define N 61

int dp[2][N][N];
int n,m,len;
int sum[N],num[N];//sum[]代表1的个数,num[]代表10进制数

int max(int a, int b) {return a > b ? a : b;}

void build()
{
    int i,tem;
    len = 0;
    for(i = 0; i < (1 << m); i++)
    {
        tem = i;
        if(((tem << 1) & i) || ((tem << 2) & i)) continue;
        num[len] = tem;
        sum[len] = 0;
        while(tem)
        {
            sum[len] += (tem & 1);
            tem = (tem >> 1);
        }
        len++;
    }
}

int match(int a, int b)
{
    int i;
    if(!a && !b) return 1;     //wa的地方!!!
    if(!b) return 0;        //wa的地方!!!
    while(a || b)
    {
        if(!(b & 1))
            if(a & 1) return 0;
        a = (a >> 1);
        b = (b >> 1);
    }
    return 1;
}

int main()
{
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    char a[110][11];
    int num2[110];//每一行代表的10进制数 
    int i,j,k,p;
    int max1,ans;
    while(~scanf("%d%d", &n, &m))
    {
        build();
        for(i = 1; i <= n; i++)
            scanf("%s", a[i]);
        for(i = 1; i <= n; i++)
        {
            num2[i] = (a[i][0] == 'P');
            for(j = 1; j < m; j++)
                num2[i] = (num2[i] << 1) + (a[i][j] == 'P');
        }
        memset(dp, 0, sizeof(dp));
        for(j = 0; j < len; j++)
        {
            if(match(num[j], num2[1]))
                for(k = 0; k < len; k++)
                    dp[1][j][k] = sum[j];
        }
        for(j = 0; j < len; j++)
        {
            if(match(num[j], num2[2]))
                for(k = 0; k < len; k++)
                    if(!(num[j] & num[k]))
                        dp[0][j][k] = dp[1][k][0]+sum[j];
        }
        for(i = 3; i <= n; i++)
        {
            for(j = 0; j < len; j++)
            {
                if(match(num[j], num2[i]))
                {
                    for(k = 0; k < len; k++)
                    {
                        if(!(num[j] & num[k]))
                        {
                            max1 = 0;
                            for(p = 0; p < len; p++)
                            {
                                if(!(num[j] & num[p]))
                                    max1 = max(max1, dp[!(i%2)][k][p]);
                            }
                            dp[i%2][j][k] = max1+sum[j];
                        }
                    }
                }
            }
        }
        ans = 0;
        for(i = 0; i < len; i++)
            for(j = 0; j < len; j++)
                ans = max(ans, dp[n%2][i][j]);
        printf("%d\n", ans);
    }
    return 0;
}

posted on 2012-07-25 00:08  andre_joy  阅读(144)  评论(0编辑  收藏  举报