C++---状态压缩dp---小国王(每日一道算法2023.4.15)

news2025/1/21 6:27:06

注意事项:
状压dp难度警告!
本题为"状态压缩dp—蒙德里安的梦想"的近似题,建议先阅读这篇文章并理解。

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

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

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

数据范围
1≤n≤10,
0≤k≤n^2

输入:
3 2
输出:
16
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

const int N = 12, M = 1 << 10, K = 110;
int n, m;                       //棋盘大小n*n, 有m个国王,
long long f[N][K][M];           //f[i][j][k],对于前i层的棋盘,总共放了j个国王,且第i层的状态为k(比如k是0101,1表示放了国王,0表示没放)的方案,
int c[M];                       //count[i]为第i层国王的数量,
vector<int> state;              //state存储所有合法状态,
vector<int> state_trans[M];     //state_trans[a] = {b1, b2, b3}存储能从合法状态a转移到的合法状态b,


bool check(int s) {     //检查当前状态(二进制)是否存在连续的两个1,存在返回false不合法,不存在返回true合法。
    for (int i = 0; i<n; i++) {
        if ((s >> i & 1) && (s >> (i+1) & 1)) return false;
    }
    return true;
}
int count(int s) {      //统计当前状态(二进制)中存在多少个1,也就是找到当前行中国王的个数。
    int res = 0;
    for (int i = 0; i<n; i++) res += (s >> i & 1);
    return res;
}

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

    //预处理所有合法方案
    for (int i = 0; i < (1<<n); i++) {
        if (check(i)) {         //如果当前状态合法,存入state,并计算状态中国王的数量。
            state.push_back(i);
            c[i] = count(i);
        }
    }

    //预处理所有合法状态可以转移到的合法状态, 满足两种情况即可转移:
    //1.状态a和状态b的&,为0,代表不存在交集, (比如01001和01010,&后就是01000,还有1存在说明肯定有两个国王会相互攻击到)
    //2.状态a和状态b的|,不能存在两个连续的1,也就是需要转移后的方案是合法方案,
    for (auto &a : state){
        for (auto &b : state) {
            if ((a&b)==0 && check(a|b)) {
                state_trans[a].push_back(b);    //符合两个条件,就说明能够从a转移到的状态b
            }
        }
    }

    //dp
    f[0][0][0] = 1;   //初始化,对于前0行,总共摆放了0个国王,且第0行的状态为0(一个都没摆),是一种合法方案。
    for (int i = 1; i<=n+1; i++) {              //枚举棋盘的每一行(枚举到n+1行是一个小优化)
        for (int j = 0; j<=m; j++) {            //枚举国王数量
            for (auto &a : state) {             //枚举合法状态a
                for (auto &b : state_trans[a]) {   //枚举所有能够从a转移到的状态b
                    if (j - c[a] >= 0) {        //如果当前剩余的国王足够摆放,就可以进行状态更新
                        f[i][j][a] += f[i-1][j-c[a]][b];
                    }
                }
            }
        }
    }
    //这里就将枚举到n+1行的优化体现出来了,f[n+1][m][0]代表,对于前n+1行,总共摆放了m个国王,且第i+1行的状态为0(一个都没摆),
    //那其实也就代表了前i行摆了m个国王的总方案数。
    cout << f[n+1][m][0];
    return 0;
}

思路:
激动人心的状压dp来了(哭),还是经典的y式dp法

1.状态表示
f[i][j][k]:
对于棋盘的前i行(包括第i行)中,已摆放j个国王,并且第i行的状态为k的方案数,
属性为Count,

(这里的状态为k指的是二进制表示一行中"国王所在的位置",例如0101,就是在第2,4格子上分别有一个国王,换算为10进制就是5,是状态压缩dp中常用的存储状态的方法)

2.状态计算
一,首先来想一下什么状态(一行)是合法的呢?
也就是对于同一行来说,国王和国王之间最少保持一格距离为合法的状态。
(图是借的彩铅大佬的,绿色是国王,红色是攻击范围):请添加图片描述

二,那再来想一下什么情况下进行状态更新(两行)是可行的呢?
也就是当a和b两个状态都是合法的前提下,
1.a和b的与运算等于0,(也就是a和b不能在相同位置上都有国王)
2.a和b的或运算的结果不存在连续的国王,(也就是结果是合法状态)
请添加图片描述

符合上述几个条件之后,终于可以进行状态转移了:
f[i][j][a] += f[i-1][j-c[a]][b]

直接从实际意义解释:
—第i行,棋盘上总摆放的国王数量为j,且第i行的状态为a,
可以从
—第i-1行,棋盘上总摆放的国王数量为"总国王数量 - 状态a的国王数量",且第i行的状态为b,
进行叠加转移。

如果有所帮助请给个免费的赞吧~有人看才是支撑我写下去的动力!

声明:
算法思路来源为y总,详细请见https://www.acwing.com/
本文仅用作学习记录和交流

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

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

相关文章

1~5年的软件测试工程师,该学习哪些知识实现涨薪20K?

工作已经8年有余&#xff0c;这8年里特别感谢技术管理人员的器重&#xff0c;以及同事的帮忙&#xff0c;学到了不少东西。这8年里走过一些弯路&#xff0c;也碰到一些难题&#xff0c;也受到过做为一名测试却经常为系统维护和发布当救火队员的苦恼。遂决定梳理一下自己所学的东…

华为暑期实习

前言&#xff1a; 多行数据需要输入的时候可以用下面的结构&#xff1a; while True:try:n int(input())s input().split()num []for i in s:num.append(int(i))k int(input())print(num[n-k])except:break输入两组数据&#xff1a; 1 8108 17 2542 4218 9064 4908 1526 …

【WLSM、FDM状态估计】电力系统状态估计研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

实验二 图像空间域频率域滤波

一&#xff0e;实验目的&#xff1a; 1. 模板运算是空间域图象增强的方法&#xff0c;也叫模板卷积。 &#xff08;1&#xff09;平滑&#xff1a;平滑的目的是模糊和消除噪声。平滑是用低通滤波器来完成&#xff0c;在空域中全是正值。 &#xff08;2&#xff09;锐化&…

ChatGPT实战100例 - (01) 秒出思维导图

文章目录ChatGPT实战100例 - (01) 秒出思维导图一、需求与思路1. 需求&#xff1a;快速的头脑风暴2. 思路&#xff1a;生成markdown然后转化嗯二、生成markdown语法的思维导图1. 问题2. 回答三、把markdown文本转换成思维导图1. 转换2. 下载ChatGPT实战100例 - (01) 秒出思维导…

Nature Communications|评估推进基于网络的蛋白质-蛋白质相互作用预测的社区工作

题目&#xff1a;Assessment of community efforts to advance network-based prediction of protein–protein interactions 文献来源&#xff1a;Nature Communications | (2023) 14:1582 4 代码&#xff1a;https://github.com/spxuw/PPI-Prediction-Project 内容&#x…

英语基础:四级431、六级没过,考研英语78分经验分享 (23考研)

前言 博主备考时的英语基础&#xff1a;英语四级431分, 六级没过 研究生英语二分数&#xff1a;78分 ps&#xff1a;也许这个分数段不是一些大佬的目标分数 (80)&#xff0c;本篇文章的目的只是帮助一些英语基础差的同学&#xff0c;提供一些备考经验。 一、基础阶段 时间&…

AI与未来文明:人工智能能否重塑人类文化,改变社会生活?

哈喽&#xff0c;大家好&#xff0c;我是木易巷&#xff01; 今天我想和大家深入探讨一个备受关注、广泛讨论的话题&#xff1a;人工智能&#xff08;AI&#xff09;及其对我们人类未来发展的影响&#xff0c;人工智能能否重塑人类文化&#xff0c;改变社会生活&#xff1f; 我…

JVM参数

GC参数 年轻代老年代参数SerialSerial Old-XX:UseSerialGCParallel ScavengeParallel Old-XX:UseParallelGC -XX:UseParallelOldGCParallel NewCMS-XX:UseParNewGC -XX:UseConcMarkSweepGCG1G1-XX:UseG1GCZGCZGC-XX:UseZGC jdk默认GC新生代老年代默认参数jdk8Parallel Scaven…

Ps 毛玻璃效果

哈喽&#xff0c;各位小伙伴&#xff01;今天我们来学习一下如何制作毛玻璃效果&#xff1f; 复制图层 导入一张图片&#xff0c;Ctrlj复制一层&#xff0c;右键—智能对象&#xff08;目的&#xff1a;方便后期更换图片&#xff09; 画矩形 画矩形(不要描边)&#xff0c;…

2023年提供优质客户服务的9种专家方法

随着我们进入 2023年&#xff0c;客户服务从未如此重要。研究表明&#xff0c;86%的客户会为良好的客户服务多支付高达 25%的费用。拥有最佳客户体验的客户比客户体验不佳的客户多花费 140%。 1.确保您拥有一支出色的客户服务团队 创造出色的客户体验意味着拥有合适的团队。但出…

Android 屏幕刷新机制与优化方案~

作者&#xff1a;阿健君 屏幕刷新机制 基本概念 刷新率&#xff1a;屏幕每秒刷新的次数&#xff0c;单位是 Hz&#xff0c;例如 60Hz&#xff0c;刷新率取决于硬件的固定参数。帧率&#xff1a;GPU 在一秒内绘制操作的帧数&#xff0c;单位是 fps。Android 采用的是 60fps&am…

小程序组件的生命周期

组件生命周期 组件的生命周期&#xff0c;指的是组件自身的一些函数&#xff0c;这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发。 其中&#xff0c;最重要的生命周期是 created attached detached &#xff0c;包含一个组件实例生命流程的最主要时间点。 …

(链表专题) 83. 删除排序链表中的重复元素 ——【Leetcode每日一题】

83. 删除排序链表中的重复元素 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2] 示例 2&#xff1a; 输入&#xff1a;he…

在线Plist文件格式转Json文件格式

Plist文件是一种用于存储应用程序配置信息的文件格式&#xff0c;其中包含应用程序的各种设置和数据。在过去&#xff0c;Plist文件通常是以 .plist 格式存储的。然而&#xff0c;随着时间的推移&#xff0c;人们开始使用 JSON 格式来存储更复杂的数据结构和数据。如果您需要将…

浏览器便携化操作方法

直接进入主题 如果我们不想把 Chrome 安装进 C 盘&#xff0c;又或者想测试多配置&#xff0c;那么浏览器的便携化就非常重要了。 浏览器便携化的方法有很多&#xff0c;国内常用的有两种。 1、MyChrome MyChrome 最早由网友“甲壳虫”开发&#xff0c;除了浏览器便携化&a…

Linux0.11 进程切换(十)

系列文章目录 Linux 0.11启动过程分析&#xff08;一&#xff09; Linux 0.11 fork 函数&#xff08;二&#xff09; Linux0.11 缺页处理&#xff08;三&#xff09; Linux0.11 根文件系统挂载&#xff08;四&#xff09; Linux0.11 文件打开open函数&#xff08;五&#xff09…

AI 写文献回顾,好使吗?

&#xff08;注&#xff1a;本文为小报童精选文章&#xff0c;已订阅小报童或加入知识星球「玉树芝兰」用户请勿重复付费&#xff09;作为一个大学老师&#xff0c;我平时少不了指导学生写论文。选题阶段很重要的工作&#xff0c;就是文献回顾。文献回顾的目的&#xff0c;是要…

jsp企业职工考勤管理系统myeclipse定制开发sqlserver数据库网页模式java编程jdbc

一、源码特点 jsp企业职工考勤管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 jsp企业职工考勤管理系统myeclipse定制开发sqls二、功能介绍 此次系统主要在JS…

Java集合框架概述

java中的集合分为单列集合(Collection)和双列集合(Map)&#xff0c;都在java.util包下&#xff0c;所有的集合框架都分为三大块内容&#xff1a;对外的接口、接口的实现、集合中的算法&#xff0c; 接口&#xff1a;代表集合的抽象数据类型&#xff0c;Collection(List、Set)、…