• POJ1185炮兵阵地(状态压缩 + dp)


    题目链接

    题意:给出一张n * m的地图,其中 有的地方能放大炮,有的地方不能,大炮与上下左右两个单位范围内会相互攻击,问最多能放几个大炮

    能放大炮为1不能放大炮为0,把每一行看做一个状态,要除去同一行与前面两个相邻的情况,然后在除去与上面两行相邻的情况,因为涉及前面两行所以多设一维状态

    dp[i][j][k]表示 第 i 行 状态为k时,第i - 1行状态为j,

    那么dp[i][j][k] = max ( dp[i][j][k], dp[i - 1][t][j] + num[k]); num[k]表示第i行可以放多少门大炮,也就是k状态下1的个数

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int state[200], num[200];
    int cur[110];
    char g[110][20];
    int dp[110][200][200];
    int n, m, top, total;
    inline bool is_ok(int x)
    {
        if (x & (x << 1))
            return 0;
        if (x & (x << 2))
            return 0;
        return 1;
    }
    int jcount(int x)
    {
        int cnt = 0;
        for (int i = 0; i < 12; i++)
            if (x & (1 << i))
                cnt++;
        return cnt;
    }
    int fit(int x, int i)
    {
        if (x & cur[i])
            return 0;
        return 1;
    }
    void init()
    {
        top = 0;
        total = 1 << m;
        for (int i = 0; i < total; i++)
        {
            if (is_ok(i))
                state[++top] = i;
        }
    }
    int main()
    {
        while (scanf("%d%d", &n, &m) != EOF)
        {
            init();
            for (int i = 1; i <= n; i++)
            {
                cur[i] = 0;
                scanf("%s", g[i] + 1);
                for(int j = 1; j <= m; j++)
                    if (g[i][j] == 'H')
                        cur[i] += (1 << (j - 1) );
    //同上一题一样将不能放炮的设为1,这样 & 的话只要非0就不行,因为一定含有不能放炮的而放炮了,0是允许放炮,但是放不放都行,也就是0,1随便,都是可以的
            }
            memset(dp, -1, sizeof(dp));
            int ans = -1;
            for (int i = 1; i <= top; i++)
            {
                num[i] = jcount(state[i]);  // 求出每一种状态下能放得炮数
                if (!fit(state[i], 1))
                    continue;
                dp[1][1][i] = num[i];  //第一行状态为state[i],第0行状态为state[1] = 0
                ans = max(ans, num[i]);
            }
            for (int i = 2; i <= n; i++)
            {
                for (int t = 1; t <= top; t++)
                {
                    if (!fit(state[t], i))
                        continue;
                    for (int j = 1; j <= top; j++) // 第 i - 1行的情况
                    {
                        if (state[t] & state[j])
                            continue;
                        for (int k = 1; k <= top; k++) //第i - 2行的情况
                        {
                            if (state[t] & state[k])
                                continue;
                            if (dp[i - 1][k][j] != -1)  // 不符合要求的,dp[1][1][其他] ,而第0行其他状态都没有
                            {
                                dp[i][j][t] = max(dp[i][j][t], dp[i - 1][k][j] + num[t]);
                                ans = max(ans, dp[i][j][t]);
                            }
                        }
                    }
                }
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    数据仓库
    数据库事务隔离级别与锁
    并发包之Future:代码级控制超时时间
    axis2 webservice 发布、调用与项目集成
    配置远程控制
    解决局部刷新的问题
    Sharepoint 2013 搜索高级配置(Search Scope)
    重启IIS报错:IIS 服务或万维网发布服务,或者依赖这 服务可能在启动期间发生错误或者已禁用
    错误提示:此产品的试用期已经结束
    Sharepoint 2013 启用搜做服务
  • 原文地址:https://www.cnblogs.com/zhaopAC/p/5322661.html
Copyright © 2020-2023  润新知