(1185)POJ-状态压缩

这道题写的我直吐血,写了6遍,不知道哪里错了,然后按照题解,一点一点写下来,跪哭了,太渣了 :(

PS:http://blog.csdn.net/cq_pf/article/details/41931061



#include<iostream>

#include<cstdio>
#include<string.h>
#include<string>
#include<stack>
#include<set>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<set>


#define ll __int64
#define lll unsigned long long
#define llf long double
#define db double
#define MAX 600
#define eps 1e-8
#define mod 100000000


using namespace std;
/*
dp[i][j][k] = max(dp[i][j][k],dp[i-1][j][k]);
第i行的状态为k,第i-1行的状态为j
H = 1 P = 0
那么判断所选状态能否在该行可行的条件就是‘&’是否为0


*/
int dp[109][109][109];//dp方程
int stk[600];//状态数
int num[600];//1的个数


int ma[509];//每行的状态
char str[109][20];//字符串


int n,m;


int lr(int x)
{
    if(x&x<<1) return 0;
    if(x&x<<2) return 0;
    return 1;
}
int _sum(int x)//数一个整型数x的二进制中1的个数(用于初始化)
{
    int cnt = 0;
    while(x)
    {
        cnt++;
        x&=(x-1);
    }
    return cnt;
}
int init()
{
    int top = 0;
    int ss = 1<<m;
    for(int i = 0; i<ss; i++)
    {
        if(lr(i))
        {
            stk[top++] = i;
        }
    }
    return top;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(dp,-1,sizeof(dp));
        for(int i = 0;i<n;i++)
        {
            scanf("%s",str[i]);
            ma[i] = 0;
            for(int j = 0;j<m;j++)
            {
                if(str[i][j]=='H')
                    ma[i]+=(1<<j);
            }
        }
        int top = init();
        for(int i =0;i<top;i++)
        {
            if(!(ma[0]&stk[i]))
            {
                dp[0][0][i] = _sum(stk[i]);
            }
        }
        for(int i = 1;i<n;i++)
        {
            for(int j = 0 ;j<top;j++)//枚举第i行的情况
            {
                if(ma[i]&stk[j])continue;//判断是否该状态是否在这一行可行
                for(int k = 0;k<top;k++)//枚举第i-1的情况
                {
                    if(stk[j]&stk[k])continue;//判断该列是否与前一列冲突
                    for(int t = 0;t<top;t++))//枚举第i-2的情况
                    {
                        if(stk[j]&stk[t])continue;)//判断该列是否与前两列冲突
                        if(dp[i-1][t][k]==-1)continue;//判断dp[i-1][s][j]是否有可能到达
                        dp[i][k][j] = max(dp[i][k][j],dp[i-1][t][k]+_sum(stk[j]));
                    }
                }
            }
        }
        int _max = 0;
        for(int i = 0;i<top;i++)
        {
            for(int j = 0;j<top;j++)
            {
                _max = max(_max,dp[n-1][i][j]);
            }
        }
        cout<<_max<<endl;
    }
    return 0;
}

你可能感兴趣的:((1185)POJ-状态压缩)