首页 > 代码库 > POJ 1185炮兵阵地

POJ 1185炮兵阵地

解题思路:

简单的状压DP,1表示放炮,预处理出每一行所有两个1间隔不小于2的状态,每一行的状态只和上面两行有关,因此可以枚举这三行的状态,用DP[i][j][k]表示第i行状态为k,第i-1行状态为j的数目,转移方程为dp[i][j][k] = max(dp[i][j][k], dp[i-1][l][j] +count(k));


#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
#include <map>
#define LL long long
#define FOR(i, x, y) for(int i=x;i<=y;i++)
using namespace std;
const int MAXNr = 100 + 10;
const int MAXNc = (1 << 11);
int dp[MAXNr][MAXNr][MAXNr];
int C[MAXNr], state[MAXNc];
char str[MAXNr][MAXNr];
int Map[MAXNr];
int N, M, K;
bool judge(int x)
{
    if(x & (x << 1)) return false;
    if(x & (x << 2)) return false;
    return true;
}
int count(int x)
{
    int res = 0;
    while(x)
    {
        if(x & 1) res++;
        x >>= 1;
    }
    return res;
}
void init()
{
    memset(Map, 0, sizeof(Map));
    int r = (1 << M) - 1; K = 0;
    FOR(i, 0, r) if(judge(i))
    state[++K] = i;
    memset(dp, -1, sizeof(dp));
}
int main()
{
    while(scanf("%d%d", &N, &M)!=EOF)
    {
        if(N == 0 && M == 0) break;
        init();
        FOR(i, 1, N) scanf("%s", str[i]+1);
        FOR(i, 1, N)
        FOR(j, 1, M) if(str[i][j] == 'H')
        Map[i] = (Map[i] | (1 << (M - j)));
        FOR(i, 1, K) if(!(state[i] & Map[1]))
        {
            dp[1][1][i] = count(state[i]);
        }

        FOR(i, 2, N)
        {
            FOR(l, 1, K)
            {
                if(state[l] & Map[i]) continue;
                FOR(j, 1, K)
                {
                    if(state[l] & state[j]) continue;
                    FOR(t, 1, K)
                    {
                        if(state[l] & state[t]) continue;
                        if(dp[i-1][t][j] == -1) continue;
                        dp[i][j][l] = max(dp[i][j][l], dp[i-1][t][j] + count(state[l]));
                    }
                }
            }
        }

        int ans = 0;
        FOR(i, 1, N)
        FOR(j, 1, K)
        FOR(k, 1, K)
        ans = max(ans , dp[N][j][k]);
        printf("%d\n", ans);
    }
    return 0;
}

 

POJ 1185炮兵阵地