POJ 1185(状态压缩dp)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include<algorithm>
using namespace std;

int dp[105][65][65];    
int s[105]; 
int n, m;      
int S;   
int map[105];  
int sum[105];


bool TwoNear(int x)
{
    if (x&(x << 1))
    {
        return false;
    }
    else if (x&(x << 2))
    {
        return false;
    }
    else
    {
        return true;
    }
}


int GetBits(int x)
{
    int num = 0;
    while (x)
    {
        if (x & 1)
        {
            num++;
        }
        x >>= 1;
    }
    return num;
}

void find()
{
    memset(s, 0, sizeof(s));
    for (int i = 0; i<(1 << m); i++)  
    {
        if (TwoNear(i))
        {
            s[S] = i;
            sum[S++] = GetBits(i);
        }

    }
}

int main()
{
    while (~scanf("%d%d", &n, &m))
    {
        memset(dp, 0, sizeof(dp));
        int r,i,j,p,q;
        for (i = 0; i<n; i++)
        {
            for (int j = 0; j<m; j++)
            {
                char temp;
                cin >> temp;
                if (temp == 'H')
                {
                    map[i] = map[i] | (1 << j);
                }
            }
        }
        S= 0;
        find();
        for (i = 0; i < S; i++)
        {
            if (!(s[i] & map[0]))
            {
                dp[0][i][0] = sum[i];
            }
        }
        for (r = 1; r<n; r++)
        {
            for (i = 0; i<S; i++)
            {
                if (map[r] & s[i])
                {
                    continue;
                }
                for (p = 0; p<S; p++)
                {
                    if (s[i] & s[p])
                    {
                        continue;
                    }
                    for ( q = 0; q<S; q++)
                    {
                        if (s[i] & s[q])
                        {
                            continue;
                        }
                        if (dp[r - 1][p][q] == 0)
                        {
                            continue;
                        }
                        dp[r][i][p] = max(dp[r][i][p], dp[r - 1][p][q] + sum[i]);
                    }
                }
            }
        }
        int Max = 0;
        for (i = 0; i<S; i++)
            for (j = 0; j<S; j++)
                Max = max(Max, dp[n - 1][i][j]);
        printf("%d\n", Max);
    }

    system("pause");
    return 0;
}

二维错误原样分析

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include<algorithm>
using namespace std;
int map[105];
int N, M;
int state[1 << 11];
int S = 0;
int dp[105][1 << 11];

int GetBits(int x)
{
    int Count = 0;
    while (x)
    {
        x = x & (x - 1);
        Count++;
    }
    return Count;
}
bool TwoNear(int x)
{
    if (x&x << 1)
        return false;
    else if (x&x << 2)
        return false;
    else
        return true;
}

void SolveRow()
{
    int i;
    for (i = 0; i < 1 << M; i++)
        if (TwoNear(i))
            state[S++] = i;
}

int main()
{

    while (~scanf("%d%d", &N, &M))
    {
        memset(dp, 0, sizeof(dp));
        memset(state, 0, sizeof(state));
        memset(map, 0, sizeof(map));
        int i, j, k, x;
        for (i = 0; i < N; i++)
        {
            for (j = 0; j < M; j++)
            {
                char ch;
                cin >> ch;
                if (ch == 'H')
                {
                    map[i] = map[i] | 1 << j;
                }
            }
        }
        SolveRow();
        for (i = 0; i <S; i++)
        {
            if (!(map[0] & state[i]))
            {
                dp[0][i] = max(dp[0][i], GetBits(state[i]));
            }
        }
        for (i = 0; i < S; i++)
        {
            for (k = 0; k < S; k++)
                if (!(map[1] & state[i]) && !(state[i] & state[k]))
                {
                dp[1][i] = max(dp[1][i], GetBits(state[i]) + GetBits(state[k]));
                }
        }
        for (i = 2; i < N; i++)
        {
            for (j = 0; j < S; j++)
            {
                if (map[i] & state[j])
                    continue;
                for (k = 0; k < S; k++)
                {
                    if (map[i - 1] & state[k] || state[k] & state[j])
                        continue;
                    for (x = 0; x < S; x++)
                    {
                        if (map[i - 2] & state[x] || state[x] & state[j] || state[x] & state[k])
                            continue;
                        else
                            dp[i][j] = max(dp[i][j], dp[i - 1][k] + GetBits(state[j]));
                        //dp[i-1][k]储存的是第i-1行时的最大可放个数,但当到第i行时,第i-2行
                        //的状态无法记录,如样例数据,当state[x]=0,state[k]=2 state[j]=1时,dp[i-1][k]=3(之前一轮循环算的),结果dp[i][j]=4;
                    }
                }
            }
        }
        int Max = 0;
        for (i = 0; i < S; i++)
            if (!(state[i] & map[N - 1]))
                Max = max(Max, dp[N - 1][i]);
        printf("%d\n", Max);
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值