POJ 1185 炮兵阵地(状态压缩DP)

题目链接:POJ 1185 炮兵阵地

状压DP第二题。。摸索中。。今天喝多了,就写了一题,堕落了。。明天奋起~

状态转移方程:dp[i][j][k] = max(dp[i][j][k], dp[i - 1][k][l] + sum[j]);,dp[i][j][k] 表示第i行的状态为j,第i - 1行的状态为k时前i行最大放置炮兵数。

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int MAX_N = 100 + 10;
const int MAX_M = 70;

int _map[MAX_N], dp[MAX_N][MAX_M][MAX_M], state[MAX_M], sum[MAX_M];
int n, m, cnt;

bool is_ok(int s)
{
    if(s & (s << 1))
       return false;
    if(s & (s << 2))
        return false;
    return true;
}

int getSum(int s)
{
    int ans = 0;
    while(s > 0)
    {
        if(s & 1)
            ans++;
        s >>= 1;
    }
    return ans;
}
void getState()
{
    int len = (1 << m);
    for(int i = 0; i < len; i++)
    {
        if(is_ok(i))
        {
            state[cnt] = i;
            sum[cnt] = getSum(i);
            cnt++;
        }
    }
}
int main()
{
    //freopen("in.txt", "r", stdin);
    memset(dp, -1, sizeof(dp));
    cnt = 0;
    memset(_map, 0, sizeof(_map));
    scanf("%d%d", &n, &m);
    char str[12];
    for(int i = 0; i < n; i++)
    {
        scanf("%s", str);
        for(int j = 0; j < m; j++)
        {
            if(str[j] == 'H')
                _map[i] |= (1 << j);
        }
    }
    getState();
    for(int i = 0; i < cnt; i ++)
        if(!(state[i] & _map[0]))
            dp[0][i][0] = sum[i];
    for(int i = 1; i < n; i++)
    {
        for(int j = 0; j < cnt; j++)
        {
            if(!(_map[i] & state[j]))
            {
                for(int k = 0; k < cnt; k++)
                {
                    if(!(state[j] & state[k]))
                    {
                        for(int l = 0; l < cnt; l++)
                        {
                            if(!(state[j] & state[l]))
                            {
                                if(dp[i - 1][k][l] == -1)
                                    continue;
                                dp[i][j][k] = max(dp[i][j][k], dp[i - 1][k][l] + sum[j]);
                            }
                        }
                    }
                }
            }
        }
    }
    int res = 0;
    for(int i = 0; i < cnt; i++)
        for(int j = 0; j < cnt; j++)
            res = max(dp[n - 1][i][j], res);
    printf("%d\n", res);
    return 0;
}


你可能感兴趣的:(POJ 1185 炮兵阵地(状态压缩DP))