POJ 1185 炮兵阵地

题意:中文题……

 

解法:状压dp。用二进制数表示一行的状态,1表示放人,0表示不放人,考虑dp[i][j][k]表示第i行状态为j,第i-1行状态为k时的人数,则有状态转移方程当状态枚举状态jkl分别表示第i行、第i-1行、第i-2行状态,当jkl互相兼容时,dp[i][j][k] = max(dp[i][j][k], dp[i - 1][k][l] + num[j]),num[i]表示状态i中的人数,状态一共有210个,所以复杂度为n×210×210×210,是不可以接受的,但因为每行里人之间的距离至少为2,所以合法的状态只有60,可以深搜得到,这样复杂度变为n×60×60×60。状态i和j兼容的条件为i&j等于0,即没有两个士兵站在同一列上,可以按同样的方法压缩地图的状态。

 

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#include<iomanip>
#define LL long long
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

using namespace std;

char maze[110][15];
int state[100];
int tot = 0;
int num[60];
void dfs(int now, int pos, int ni)
{
    num[tot] = ni;
    state[tot++] = now;
    for(int i = pos + 3; i < 10; i++)
    {
        int tmp = 1 << i;
        dfs(now | tmp, i, ni + 1);
    }
}
int dp[105][60][60];
int M[105];
int main()
{
    dfs(0, -3, 0);
    int n, m;
    while(~scanf("%d%d", &n, &m))
    {
        memset(M, 0, sizeof M);
        for(int i = 1; i < n + 1; i++)
        {
            scanf("%s", maze[i]);
            for(int j = 0; j < 10; j++)
            {
                M[i] <<= 1;
                if(maze[i][j] != 'P') ++M[i];
            }
        }
        memset(dp, 0, sizeof dp);
        for(int i = 1; i < n + 1; i++)
        {
            for(int j = 0; j < 60; j++)
            {
                for(int k = 0; k < 60; k++)
                {
                    for(int l = 0; l < 60; l++)
                    {
                        if(state[l] & M[i]) continue;
                        if(state[j] & state[k]) continue;
                        if(state[j] & state[l]) continue;
                        if(state[k] & state[l]) continue;
                        dp[i][l][k] = max(dp[i][l][k], dp[i - 1][k][j] + num[l]);
                    }
                }
            }
        }
        int ans = 0;
        for(int i = 0; i < 60; i++)
            for(int j = 0; j < 60; j++)
                ans = max(dp[n][i][j], ans);
        printf("%d\n", ans);
    }
    return 0;
}

  

posted @ 2015-11-03 10:06  露儿大人  阅读(154)  评论(0编辑  收藏  举报