poj 1185 炮兵阵地 (状态压缩dp)

简介: 如果你是刚刚开始做状态压缩dp,我建议你先看看 poj 3254 Corn Fields 这是一道比这一题更简单,更容易入门的题目。 还有在代码中我用了一个很巧妙的方法求一个数二进制数中1的个数 具体请看我博客中 x& (x - 1)==0 这篇文章 链接 。

题目链接


    如果你是刚刚开始做状态压缩dp,我建议你先看看 poj 3254 Corn Fields 这是一道比这一题更简单,更容易入门的题目。

   还有在代码中我用了一个很巧妙的方法求一个数二进制数中1的个数  具体请看我博客中  x& (x - 1)==0 这篇文章  链接  。

    还有一点,不同于poj 3254的地方,我们不能直接枚举所有的状态。我在getresult()中用到了四重循环,直接枚举的时间复杂度是2^40,并且dp那个数组也是开不下到,不过对于这道题还是有方法的。枚举一行所有的状态,行合法(没有两个1相隔少于两个)的状态总共有61中,我们只需要枚举所有合法状态即可,循环次数最多是61^4。


代码

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxn = 62;          //每行合法的状态总共有61种
int dp[102][maxn][maxn];      //因为状态是与前两行有关,所以用到三维数组
int sta[102];                 //每行不能放置的点
int cnt[maxn];                //状态中1的数目,也就是炮的数目
int allsta[maxn];             //所有可能的状态
int n, m;
int num;                      //满足条件的状态数
bool judgeself(int x)         //判断x状态是不是有会相互攻击的状态,也就是有没有两个1相隔少于两个0
{
    if (x&(x<<1) || x&(x<<2))
        return false;
    return true;
}
int count(int x)              //用很巧妙的计算出x二进制中1的个数
{
    int s = 0;
    while (x)
    {
        s++;
        x = x&(x-1);
    }
    return s;
}
void search(int x)
{                                   //这个函数相当于把对状态进行了离散化,去掉了每行所有不合法的状态
    int t = 1<<x;
    num = 0;
    for (int i = 0; i < t; i++)
    {
        if (judgeself(i))
        {
            allsta[num] = i;
            cnt[num] = count(i);
            num++;
        }
    }
}
bool fit(int x, int y)
{
    if(x&y)
        return false;
    return true;
}
void getresult()
{
    memset(dp, 0, sizeof(dp));
    for (int i = 0; i < num; i++)              //因为计算每行的时候需要用到前两行的状态,需要对第一行特殊处理
    {
        for (int j = 0; j < num; j++)
        {
            if (fit(sta[1], allsta[i]) && fit(allsta[i], allsta[j]))
                dp[1][j][i] = cnt[i];
        }
    }
    for (int i = 2; i <= n; i++)
    {
        for (int j = 0; j < num; j++)
        {
            if (!fit(sta[i], allsta[j]))
                continue;
            for (int k = 0; k < num; k++)
            {
                if (!fit(allsta[j], allsta[k]))           // 判断是否与前一行冲突
                    continue;
                for (int l = 0; l < num; l++)
                {
                    if (!fit(allsta[j], allsta[l]))       //不光要判断是否与前一行冲突,要判断第前两行
                        continue;
                    dp[i][k][j] = max(dp[i][k][j], dp[i-1][l][k]+cnt[j]);
                }
            }
        }
    }
    int ans = 0;
    for (int i = 0; i < num; i++)
    {
        for (int j = 0; j < num; j++)
        {
            if (!fit(allsta[i], allsta[j]))
                continue;
            ans = max(ans, dp[n][i][j]);              //求出最后一行最大的结果
        }
    }
    printf("%d\n", ans);
}
int main()
{
    while (scanf("%d %d", &n, &m) != EOF)
    {
        memset(sta, 0, sizeof(sta));
        search(m);
        for (int i = 1; i <= n; i++)
        {
            getchar();
            for (int j = 1; j <= m; j++)
            {
                char t;
                scanf("%c", &t);
                if (t == 'H')
                    sta[i] += (1<<(m-j));            //标记一行中不能安放炮兵的状态
            }
        }
        getresult();
    }
    return 0;
}
目录
相关文章
|
算法 安全 定位技术
地图一共有多少个坐标系?有什么区别?如何选择?
地图一共有多少个坐标系?有什么区别?如何选择?
2035 11
|
算法
【算法】滑动窗口——将x减到0的最小操作数
【算法】滑动窗口——将x减到0的最小操作数
147 0
|
Java 微服务 Spring
|
算法 Shell Linux
正则表达式基础 | 学习笔记
快速学习正则表达式基础。
239 0
|
数据安全/隐私保护 Android开发
|
消息中间件
Qt之进程间通信(IPC)
简述 进程间通信,就是在不同进程之间传播或交换信息。那么不同进程之间存在着什么双方都可以访问的介质呢?进程的用户空间是互相独立的,一般而言是不能互相访问的,唯一的例外是共享内存区。但是,系统空间却是“公共场所”,所以内核显然可以提供这样的条件。除此以外,那就是双方都可以访问的外设了。在这个意义上,两个进程当然也可以通过磁盘上的普通文件交换信息,或者通过“注册表”或其它数据库
2859 0
|
.NET 程序员 C#
C#对象的销毁和IDisposable
1.对象的析构函数与Finalize方法 与C++类似,C#允许程序员为类定义一个”析构函数“: class MyClass { ~MyClass() //析构函数 { //编写释放非托管的资源 } }  上面的代码编译后,可以看到: 这里调用了Object类的Finalize方法,这个方法里面是空的,什么也没有。
961 0
|
4天前
|
云安全 人工智能 算法
以“AI对抗AI”,阿里云验证码进入2.0时代
三层立体防护,用大模型打赢人机攻防战
1319 4
|
4天前
|
机器学习/深度学习 安全 API
MAI-UI 开源:通用 GUI 智能体基座登顶 SOTA!
MAI-UI是通义实验室推出的全尺寸GUI智能体基座模型,原生集成用户交互、MCP工具调用与端云协同能力。支持跨App操作、模糊语义理解与主动提问澄清,通过大规模在线强化学习实现复杂任务自动化,在出行、办公等高频场景中表现卓越,已登顶ScreenSpot-Pro、MobileWorld等多项SOTA评测。
671 3