1.5状态压缩DP

news2024/11/17 17:30:18

1.小国王

n × n n×n n×n的棋盘上放 k k k个国王,国王可攻击相邻的 8 8 8个格子,求使它们无法互相攻击的方案总数。

输入格式
共一行,包含两个整数 n n n k k k

输出格式
共一行,表示方案总数,若不能够放置则输出 0 0 0

数据范围
1 ≤ n ≤ 10 , 1≤n≤10, 1n10,
0 ≤ k ≤ n 2 0≤k≤n^{2} 0kn2
输入样例:

3 2

输出样例:

16
1.1题解

在这里插入图片描述

在这里插入图片描述
因此这会导致,两斜对角国王相互攻击。

综上所述,我们得到集合转移的约束条件。

下面是代码部分,有很详细的解说
在这里插入图片描述

1.2代码实现
#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 12, M = 1 << 10, K = 110;

int n,m;
int cnt[M]; //记录该状态中 1 的个数,即该状态所能摆放的国王个数
LL f[N][K][M]; //前 i 行已经摆好,且已摆放好 j 个国王,第 i 行状态是 a 的方案
vector<int> state; //合法的状态
vector<int> head[M]; //该状态能够转移的状态

//判断该状态是否有相邻的 1,若没有则合法
bool check(int state)
{
    return !(state&state>>1);
}

//统计该状态中 1 的个数
int count(int state)
{
    int res=0;
    for(int i=0;i<n;i++) res+=state>>i&1;
    return res;
}

int main()
{
    cin>>n>>m;

    //筛选出合法的状态
    for(int i=0;i<1<<n;i++)
        if(check(i))
        {
            state.push_back(i);
            cnt[i]=count(i); //记录该状态中 1 的个数
        }

    //枚举出该状态所能转移到的状态
    for(int i=0;i<state.size();i++)
        for(int j=0;j<state.size();j++)
        {
            int a=state[i],b=state[j];
            if(!(a&b)&&check(a|b)) //能够转移的条件
                head[a].push_back(b); //状态 a 和状态 b 之间可互相转移
        }

    f[0][0][0]=1;
    for(int i=1;i<=n+1;i++)
        for(int j=0;j<=m;j++)
            for(auto a : state) //枚举第 i 行的状态
                for(auto b : head[a]) //枚举第 i - 1 行的状态
                    if(j>=cnt[a]) 
                        f[i][j][a]+=f[i-1][j-cnt[a]][b]; //状态 a 可由状态 b 转移过来

    // LL res=0;
    // for(auto x : state) res+=f[n][m][x];
    // cout<<res<<endl;
    // 上述代码等价于f[n+1][m][0]
    cout<<f[n+1][m][0]<<endl;

    return 0;
}

2.玉米田

农夫约翰的土地由 M × N M×N M×N个小方格组成,现在他要在土地里种植玉米。

非常遗憾,部分土地是不育的,无法种植。

而且,相邻的土地不能同时种植玉米,也就是说种植玉米的所有方格之间都不会有公共边缘。

现在给定土地的大小,请你求出共有多少种种植方法。

土地上什么都不种也算一种方法。

输入格式

1 1 1行包含两个整数 M M M N N N

2.. M + 1 2..M+1 2..M+1行:每行包含 N N N个整数 0 0 0 1 1 1,用来描述整个土地的状况, 1 1 1表示该块土地肥沃,0表示该块土地不育。

输出格式

输出总种植方法对 1 0 8 10^{8} 108取模后的值。

数据范围
1 ≤ M , N ≤ 12 1≤M,N≤12 1M,N12

输入样例:

2 3
1 1 1
0 1 0

输出样例:

9
2.1题解

在这里插入图片描述
算法构造
经典的棋盘型状态压缩动态规划,我们可以按照之前Acwing上P1064小国王的思路,处理本题。

首先,我们需要明确,题目的要求:

  1. 统计方案数
  2. 有些土地不能种植

状态设计
首先,我们得明确状态是什么。

我们这个状态,肯定是要统计方案数。

我们这个状态,必然需要表示每一行土地种植的状态。

因此得到:

f [ i ] [ s ] 表示已经种植前 i 行,且第 i 行种植的状态为 s 的方案数 f[i][s]表示已经种植前i行,且第i行种植的状态为s的方案数 f[i][s]表示已经种植前i行,且第i行种植的状态为s的方案数

状态转移
题目的限制条件,其实就是我们转移的限制条件。

我们知道,这里是十字形的禁止种植,也就是上下左右不能有相邻的两棵玉米。

那么怎么判断呢?

如果说我们把 1 1 1表示这个地方种植玉米, 0 0 0表示不种植
S = 11101 , 2 , 3 这三个地方种玉米,第四个地方不种植玉米 S=11101,2,3这三个地方种玉米,第四个地方不种植玉米 S=11101,2,3这三个地方种玉米,第四个地方不种植玉米

对于一行而言,不能种植相邻的玉米。

即:

对于一行而言,不能有相邻的 1 1 1
S = 1110 是不合法的状态 S=1110是不合法的状态 S=1110是不合法的状态

对于相邻的两行而言,不能在同一列都种植玉米

a = 1010 b = 1000 这是不可以的,在第一个位置会出现上下矛盾 a=1010\\ b=1000\\ 这是不可以的,在第一个位置会出现上下矛盾 a=1010b=1000这是不可以的,在第一个位置会出现上下矛盾
那么我们可以转化为:
在这里插入图片描述
最后,对于题目中的土地不能种植,我们可以认为。
如果第 i 行的状态为 s ,那么荒废土地处不能有 1 如果第i行的状态为s,那么荒废土地处不能有1 如果第i行的状态为s,那么荒废土地处不能有1

我们可以设计一个数组:
g [ i ] 表示第 i 行不能种植土地的状态 g [ 1 ] = 1011 表示第一行,第一个,第三个,第四个位置不能种植玉米 g[i]表示第i行不能种植土地的状态\\g[1]=1011表示第一行,第一个,第三个,第四个位置不能种植玉米 g[i]表示第i行不能种植土地的状态g[1]=1011表示第一行,第一个,第三个,第四个位置不能种植玉米
总而言之

在这里插入图片描述

2.2代码实现
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 14, M = 1 << 12, mod = 1e8;

int n, m;
int w[N];
vector<int> state;
vector<int> head[M];
int f[N][M];

//判断有没有相邻的两个1
bool check(int state)
{
    for (int i = 0; i + 1 < m; i ++ )
        if ((state >> i & 1) && (state >> i + 1 & 1))
            return false;
    return true;
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ )
        for (int j = 0; j < m; j ++ )
        {
            int t;
            cin >> t;
            //荒废土地是0,我们在次转换为1
            w[i] += !t * (1 << j);
        }

    for (int i = 0; i < 1 << m; i ++ )
        if (check(i))//这个状态不存在种植左右相邻的玉米
            state.push_back(i);

    for (int i = 0; i < state.size(); i ++ )
        for (int j = 0; j < state.size(); j ++ )
        {
            int a = state[i], b = state[j];
            if (!(a & b))//a对应的状态和j对应的状态没有在同一列种植玉米
                head[i].push_back(j);
        }

    f[0][0] = 1;
    for (int i = 1; i <= n + 1; i ++ )
        for (int j = 0; j < state.size(); j ++ )
        //在第i行,状态j是否满足在荒废土地上种植玉米
            if (!(state[j] & w[i]))
            //从上一行j对应的状态,转到本行i对应的状态
                for (int k : head[j])
                    f[i][j] = (f[i][j] + f[i - 1][k]) % mod;
    //表示第n+1行什么都没种植的状态,其实就是累加f[n][S]
    cout << f[n + 1][0] << endl;

    return 0;
}


3.炮兵阵地

司令部的将军们打算在 N × M N×M N×M的网格地图上部署他们的炮兵部队。

一个 N × M N×M N×M的地图由 N N N M M M列组成,地图的每一格可能是山地(用 H H H 表示),也可能是平原(用 P P P 表示),如下图。

在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:

在这里插入图片描述
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。

图上其它白色网格均攻击不到。

从图上可见炮兵的攻击范围不受地形的影响。

现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。

输入格式
第一行包含两个由空格分割开的正整数,分别表示 N N N M M M

接下来的 N N N行,每一行含有连续的 M M M 个字符( P P P 或者 H H H),中间没有空格。按顺序表示地图中每一行的数据。

输出格式
仅一行,包含一个整数 K K K,表示最多能摆放的炮兵部队的数量。

数据范围
N ≤ 100 , M ≤ 10 N≤100,M≤10 N100,M10
输入样例:

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

输出样例:

6

只看了一半…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1115706.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RHEL 8.6 Kubespray 1.23.0 install kubernetes v1.27.5

文章目录 1. 预备条件2. download01 节点 安装 dockerdownload01 节点 介质下载下载 bastion01节点配置 yum 源bastion01 节点安装 docker5. 安装 docker insecure registrybastion01 部署 nginx 与 镜像入库13.1 配置 config.sh13.2 配置 setup-docker.sh13.3 配置 start-ngin…

18-spring 事务

文章目录 1. xml和注解配置方式的对象2.spring事务传播特性3. 注解事务的初始化流程4. 创建事务信息流程图5. 事务回滚流程图1. xml和注解配置方式的对象 2.spring事务传播特性 事务传播行为类型说明PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事…

控制器连接Profinet转Modbus RTU网关与精密数显温控仪通讯配置案例

Profinet是一种用于工业自动化领域的通信协议&#xff0c;而Modbus RTU则是一种常见的串行通信协议。由于生产现场中的控制器与精密数显温控仪通常采用不同的通信协议&#xff0c;因此需要借助Profinet转Modbus RTU网关&#xff08;XD-MDPN100&#xff09;完成通信的桥接与转换…

SystemVerilog学习(1)——验证导论

写在最前 选课不慎&#xff0c;选修课选了个SystemVerilog&#xff0c;事情比必修还多&#xff0c;上课老师讲的一点用没有&#xff0c;但是学分还得修&#xff0c;只能自学了&#xff0c;既来之则安之。 一、什么是SystemVerilog SystemVerilog简称为SV语言&#xff0c;是一种…

攻防世界web篇-get_post

打开给出的地址 将浏览器上的地址http://61.147.171.105:58937/改为http://61.147.171.105:58937/?a1 输入?a1是完成了第一步&#xff0c;get请求&#xff0c;接下来要完成post的请求 这里&#xff0c;我使用的backbar quantum插件 得出flag值

【剑指Offer】32.从上往下打印二叉树

题目 不分行从上往下打印出二叉树的每个节点&#xff0c;同层节点从左至右打印。例如输入{8,6,10,#,#,2,1}&#xff0c;如以下图中的示例二叉树&#xff0c;则依次打印8,6,10,2,1(空节点不打印&#xff0c;跳过)&#xff0c;请你将打印的结果存放到一个数组里面&#xff0c;返…

深度强化学习 第 4 章 DQN 与 Q 学习

4.1 DQN 最优动作价值函数的用途 假如我们知道 Q ⋆ Q_⋆ Q⋆​&#xff0c;我们就能用它做控制。 我们希望知道 Q ⋆ Q_⋆ Q⋆​&#xff0c;因为它就像是先知一般&#xff0c;可以预见未来&#xff0c;在 t 时刻就预见 t 到 n时刻之间的累计奖励的期望。假如我们有 Q ⋆ Q…

【关于FPGA内部die到pin的延时数据,即pin delay获取方法】

首先&#xff0c;本文只介绍Xilinx的&#xff0c;Alteral的以后。。 第一&#xff0c;生成平台 Xilinx目前在用的是ISE,和Vivado&#xff1b;二者之间并不是可以互相替代的&#xff0c;或者说这两者不完全是迭代的关系。 第二&#xff0c;先介绍常用的–VIVADO 这里又有几种…

Linux系统之passwd命令的基本使用

Linux系统之passwd命令的基本使用 一、passwd命令介绍1.1 passwd命令简介1.2 passwd命令起源 二、passwd命令的使用帮助2.1 passwd命令的help帮助信息2.2 passwd命令的语法解释 三、查看passwd相关文件3.1 查看用户相关文件3.2 查看组相关文件 四、passwd命令的基本使用4.1 设置…

mysql MVC jsp实现表分页

mysql是轻量级数据库 在三层架构中实现简单的分页 在数据库sql编程中需要编写sql语句 SELECT * FROM sys.student limit 5,5; limit x,y x是开始节点&#xff0c;y是开始节点后的需要显示的长度。 在jdbc编程中需要给出x和y 一般是页数*页码&#xff0c;显示的长度。 代…

谷歌云:下一代开发者和企业解决方案的强力竞争者

自从2018年Oracle前研发总裁Thomas Kurian加入谷歌云&#xff08;Google Cloud&#xff09;并出任谷歌云CEO以来&#xff0c;业界对于谷歌云的发展就十分好奇。而谷歌云的前任CEO Diane Greene曾是VMware的创始人之一&#xff0c;那么两任企业级技术和解决方案出身的CEO&#x…

windows上下载github上的linux内核项目遇到的问题

问题一&#xff1a;clone的时候报错 Cloning into G:\github\linux... POST git-upload-pack (gzip 27925 to 14032 bytes) remote: Counting objects: 6012062, done. remote: Compressing objects: 100% (1031/1031), done. remote: Total 6012062 (delta 893), reused 342 (…

Android推送问题排查

针对MobPush智能推送服务在使用过程中可能出现的问题&#xff0c;本文为各位开发者们带来了针对MobPush安卓端推送问题的解决办法。 TCP在线推送排查 排查TCP在线收不到推送时&#xff0c;我们先通过客户端的RegistrationId接口获取设备的唯一标识 示例&#xff1a; MobPush…

【Reinforcement Learning】Ubuntu中mujoco210 mujoco_py D4RL安装及错误解决

Ubuntu中mujoco210 mujoco_py D4RL安装及错误解决 本文根据一篇知乎文章链接在此进行配置&#xff0c;记录在配置过程中遇到的一些问题&#xff0c;原文作者的教程很详细&#xff0c;在此对原作者表示感谢&#xff5e; 直接进行知乎原文的第2.2 有效安装过程(避坑) 2.注意上…

行业领先的三个企业正在利用聊天机器人变得更强

聊天机器人已成为客户服务领域的革命者&#xff0c;深刻地改变了企业与客户互动的方式。这些虚拟助手简化了交互&#xff0c;提供了24/7全天候高效和个性化的支持。凭借先进的技术和自然语言处理能力&#xff0c;聊天机器人擅长快速处理查询。 效率是聊天机器人的关键优势。它…

《数据结构、算法与应用C++语言描述》-队列的应用-图元识别问题

《数据结构、算法与应用C语言描述》-队列的应用-图元识别问题 图元识别 问题描述 数字化图像是一个 mxm 的像素矩阵。在单色图像中&#xff0c;每一个像素要么为0&#xff0c;要么为 1。值为0的像素表示图像的背景。值为1的像素表示图元上的一个点&#xff0c;称其为图元像素…

A_搜索(A Star)算法

A*搜索(A Star) 不同于盲目搜索&#xff0c;A算法是一种启发式算法(Heuristic Algorithm)。 上文提到&#xff0c;盲目搜索对于所有要搜索的状态结点都是一视同仁的&#xff0c;因此在每次搜索一个状态时&#xff0c;盲目搜索并不会考虑这个状态到底是有利于趋向目标的&#x…

STM32使用WWDG窗口看门狗

1 WWDG 介绍 1.1 WWDG 简介 窗口看门狗 WWDG 其实和独立看门狗类似&#xff0c;它是一个 7 位递减计数器不断的往下递减计数&#xff0c; 当减到一个固定值 0X40 时还不喂狗的话&#xff0c;产生一个 MCU 复位&#xff0c;这个值叫窗口的下限&#xff0c;是固定的值&#xf…

Android 开发技巧:音乐播放器的后台处理【Service、Handler、MediaPlayer】

给定部分完成的MusicPlayer项目&#xff0c;实现其中未完成的service部分&#xff1a; 1、创建MusicService类&#xff0c;通过service组件实现后台播放音乐的功能&#xff1b; 2、在MainActivity中通过ServiceConnection连接MusicService&#xff0c;实现对音乐播放的控制&…

Android端自定义铃声

随着移动应用竞争进入红海时代&#xff0c;如何在APP推送中别出心裁显得尤为重要。例如对自己的APP推送赋予独特的推送铃声&#xff0c;能够给用户更加理想的使用体验。 1、个性化提醒铃声有助于当收到特定类型的消息时&#xff0c;用户能够立刻识别出来。 2、不同的推送铃声…