动态规划算法刷题笔记【状压dp】

news2025/1/16 5:57:09

二进制枚举子集

在这里插入图片描述
a&1 == 1 判断是否为奇数,如果为1,则为奇数因为奇数二进制末位一定是1,所以 与1 得到的结果是1

在这里插入图片描述
在这里插入图片描述
这里,1<<14——214——第15位是1,可以表示14个1
i&(1<<j)—— 从0开始是因为,原本第1位就是1。所以j=0时,对应的就是 i 的最低位

在这里插入图片描述

状态压缩

在这里插入图片描述

旅行商问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Floyd算法:

在这里插入图片描述

方格取数问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
now | flag == flag —— (1代表可以选择,0代表不可以选择):

10110
00110
= 10110 == flag

10110
01001
= 11111 != flag

使用条件

  • 状态需要有一定的状态单元。 即一个状态应该是保存一个集合,其中的元素值对应着0或1,例如我们常见的棋盘,我们可以用0或1来表示棋子的放置状态。而整个集合即是一个01串,即二进制数,我们通常用十进制表示。那么我们再进行状态转移或者判断的时候,需要先将十进制转化为二进制,再将二进制转化为十进制
  • 题目中限制的集合大小不会超过20。 如果用二进制表示状态,那么集合大小为20的二进制状态有220-1,已经达到1e7的数量级了
  • 具有动态规划的特性。 对于动态规划,一般都是要求最优化某个值,具有最优子结构的性质。同时也需要满足状态转移的特性,而不是前一个状态毫无关系的

[SCOI2005] 互不侵犯

在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。

输入格式

只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)

输出格式

所得的方案数

样例输入 #1

3 2

样例输出 #1

16

思路

  • 还是比较模板的一道题
  • 国王的意思是:选定了格子,然后不能相邻(斜上方、斜下方)。跟方格取数差不多
  • 首先对第1行进行处理,这样后面的行才能使用模板
  • 循环模板:1. 枚举行。——2. 枚举上个阶段放了的国王数。——3. 枚举本阶段的状态。——4. 在枚举本阶段状态的同时,枚举上一阶段的状态,维护状态。

题解

#include<bits/stdc++.h>
using namespace std;
long long ans,n,m,k,f[10][100][1<<9+5];
int lowbit(int x){
	int tmp=0;
	while(x) tmp++,x-=x&(-x);
	return tmp;
}
int main(){
	scanf("%lld%lld",&n,&k);
	m=(1<<n)-1;
	for(int i=0;i<=m;++i){
		if(!(i&(i<<1))&&lowbit(i)<=k) 
		f[1][lowbit(i)][i]=1;
	} 
	//处理出第一行的所有情况 
	for(int i=2;i<=n;++i)//枚举行 
	for(int j=0;j<=k;++j)//枚举上个阶段放了的国王数 
	for(int x=0;x<=m;++x){//枚举本阶段的状态 
		if(x&(x<<1)) continue;//本阶段不能互相伤害 
		for(int y=0;y<=m;++y){//枚举上一个阶段的状态 
			if(x&y||x&(y<<1)||x&(y>>1)) continue;//本状态和上一个状态不能冲突
			if(j+lowbit(x)>k) continue;//本状态新放的国王数目+上个阶段国王数小于k 
			f[i][j+lowbit(x)][x]+=f[i-1][j][y];  //本状态加上一状态数 
		}
	}
	for(int j=0;j<=m;++j) ans+=f[n][k][j];
	printf("%lld",ans);
}

[NOI2001] 炮兵阵地

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

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

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

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

图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。

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

输入格式

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

接下来的 N N N 行,每一行含有连续的 M M M 个字符,按顺序表示地图中每一行的数据。

输出格式

一行一个整数,表示最多能摆放的炮兵部队的数量。

样例输入 #1

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

样例输出 #1

6

提示

对于 100 % 100\% 100% 的数据, N ≤ 100 N\le 100 N100 M ≤ 10 M\le 10 M10,保证字符仅包含 PH

思路

  • 这道题还是有些复杂的
  • 按照思路:1. 初始化(对第1行操作、枚举合法状态)。2. 状态转移。(循环判断后面的行是否合法——判断 i-1,i-2)

题解

#include<bits/stdc++.h>
using namespace std;
int n,m,num[60];
char s[110][15]; 
int rec[110];
int state[70],top;
int dp[110][70][70];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<(1<<m);i++){
		if((i&(i<<1)||(i&(i<<2))))continue; 
		int k=i;
		while(k){
			++num[top];
			k&=(k-1);
		}
		state[top++]=i;
	}
	for(int i=0;i<n;i++){
		cin>>s[i];
		for(int j=0;j<m;j++)
			if(s[i][j]=='H')
		 	rec[i]|=(1<<j); 
	}
	for(int i=0;i<top;i++) {
		if(state[i]&rec[0])continue;
		dp[0][0][i]=num[i];
	}
	for(int i=1;i<n;i++){
		for(int j=0;j<top;j++) {
			if(state[j]&rec[i])continue; 
			for(int k=0;k<top;k++) {
				if(state[j]&state[k])continue;
				for(int t=0;t<top;t++) {
					if(state[j]&state[t])continue; 
					if(state[k]&state[t])continue;
					dp[i][k][j]=max(dp[i][k][j],dp[i-1][t][k]+num[j]); 
				}
			}
		}
	}
	int ans=0;
	for(int i=0;i<n;i++)
		for(int j=0;j<top;j++)
			for(int k=0;k<top;k++)
				ans=max(ans,dp[i][j][k]);
	printf("%d",ans);
}

[USACO06NOV]Corn Fields G

Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and can’t be planted. Canny FJ knows that the cows dislike eating close to each other, so when choosing which squares to plant, he avoids choosing squares that are adjacent; no two chosen squares share an edge. He has not yet made the final choice as to which squares to plant.

Being a very open-minded man, Farmer John wants to consider all possible options for how to choose the squares for planting. He is so open-minded that he considers choosing no squares as a valid option! Please help Farmer John determine the number of ways he can choose the squares to plant.

农场主 J o h n \rm John John 新买了一块长方形的新牧场,这块牧场被划分成 M M M N N N ( 1 ≤ M ≤ 12 ; 1 ≤ N ≤ 12 ) (1 \le M \le 12; 1 \le N \le 12) (1M12;1N12),每一格都是一块正方形的土地。 J o h n \rm John John 打算在牧场上的某几格里种上美味的草,供他的奶牛们享用。

遗憾的是,有些土地相当贫瘠,不能用来种草。并且,奶牛们喜欢独占一块草地的感觉,于是 J o h n \rm John John 不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。

J o h n \rm John John 想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择?(当然,把新牧场完全荒废也是一种方案)

输入格式

第一行:两个整数 M M M N N N,用空格隔开。

2 2 2 到第 M + 1 M+1 M+1 行:每行包含 N N N 个用空格隔开的整数,描述了每块土地的状态。第 i + 1 i+1 i+1 行描述了第 i i i 行的土地,所有整数均为 0 0 0 1 1 1 ,是 1 1 1 的话,表示这块土地足够肥沃, 0 0 0 则表示这块土地不适合种草。

输出格式

一个整数,即牧场分配总方案数除以 100 , 000 , 000 100,000,000 100,000,000 的余数。

样例输入 #1

2 3
1 1 1
0 1 0

样例输出 #1

9

思路

  • f[i][j]表示在前i行中(包括i)在j个状态下的最大方案数,f[i][j]=(f[i][j]+f[i-1][k])
  • 判断枚举出的状态是否符合题目要求
  • 先对第1行进行初始化

题解

#include<bits/stdc++.h>
typedef long long ll;
const int p=100000000;
using namespace std;
int M,N,a[13][13],check[1<<12],ans=0;
ll f[13][1<<12],F[13];
int main(){
    scanf("%d%d",&M,&N);
    for(int i=1;i<=M;++i) for(int j=1;j<=N;++j) scanf("%d",&a[i][j]);
    for(int i=1;i<=M;++i) for(int j=1;j<=N;++j) F[i]=(F[i]<<1)+a[i][j]; //将第i行的可不可以种草的01状态用F[i]表示
    for(int i=0;i<(1<<N);++i){
        if(!(i&(i>>1))&&!(i&(i<<1))){
            check[i]=1; //记录合法状态,避免后面重复检测
            if((i&F[1])==i) f[1][i]=1; //i&F[i]==i,相同的情况:F[i]中的1≥i(二进制),也就是i——可以种草但不种。
        }
    }
    for(int i=2;i<=M;++i){            //从第2行开始
        for(int j=0;j<(1<<N);++j){
            if(((j&F[i-1])==j)&&check[j]){ //检查上一行,并枚举状态
                for(int k=0;k<(1<<N);++k){//枚举当前行的状态
                    if(((k&F[i])==k)&&!(j&k)&&check[k]) f[i][k]=(f[i][k]+f[i-1][j])%p;//当前行的数量+上一行在j状态下的数量
                }
            }
        }
    }
    for(int i=0;i<(1<<N);++i) ans=(ans+f[M][i])%p;//直接加最后一行,枚举所有的状态
    printf("%d\n",ans);
}

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

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

相关文章

Linux|奇怪的知识---CPU温度监控

前言&#xff1a; 最近我的台式机电脑CPU风扇由于积灰严重&#xff0c;噪音比较大&#xff0c;因此更换了CPU风扇。 更换比较简单没什么好说的&#xff0c;但我想清楚的知道我的CPU温度到底是多少&#xff0c;进而知道这个新风扇是否能给CPU一个清凉的环境&#xff0c;因此需…

20230125使AIO-3568J开发板在Android12下默认为简体中文

20230125使AIO-3568J开发板在Android12下默认为简体中文 2023/1/25 10:05 缘起&#xff1a;国人还是喜欢看简体中文的菜单&#xff01;^_ 百度搜索&#xff1a;rk3568 android 12 中文 CSDN&#xff1a;rk3568 ANDROID11 中文 1、build/make/target/product/full_base.mk Z:\an…

Mongodb下载与安装

Mongodb下载https://pan.baidu.com/s/1mFRK3Cn0jW_ysmC9HaGvzg 提取码&#xff1a;0068 下载完成后解压&#xff1b; 设置数据存储位置&#xff1a; bin目录新建文件夹&#xff1a; data下再新建db文件夹&#xff1a; bin目录下cmd&#xff1b; 设置数据存储位置&#x…

centos7安装RocketMQ教程

安装rocketmq 安装RocketMQ首先你的系统上得有JDK的环境&#xff0c;最低1.8 安装JDK 这里我以centos7为例进行安装 #64位 wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24http%3A%2F%2Fwww.oracle.com%2F; oraclelicenseaccept-securebackup-co…

为 TDesignBlazor 添加暗黑模式

本文将讲述我为 TDesignBlazor 开源项目提交 PR 的经历&#xff0c;主要介绍暗黑模式功能的实现以及之后如何在项目中使用。我将会分享我在实现这一功能时遇到的问题&#xff0c;以及我是如何解决这些问题的。我希望通过我的经历能够鼓励更多的人参与开源项目&#xff0c;为 TD…

CE训练教程进阶,步骤 9: 注入++

目录 一、找出存放四个玩家健康值的地址 二、找出修改数据的代码 三、找出是谁调用了修改指令 四、分析玩家的内存数据 五、注入修改代码 六、C语言代码注入 相对于前面8个步骤&#xff0c;步骤9稍微要难一点&#xff0c;所以单独写。 步骤9是在步骤7的基础上&#xff0c…

Flowable进阶学习(六)网关

文章目录排他网关案例&#xff1a;并行网关案例&#xff1a;包容网关案例&#xff1a;事件网关网关(gateway)用来控制流程的流向。来实现复杂的审批流程。网关的分类包括&#xff1a;排他网关、并行网关、包容网关、事件网关。排他网关 exclusive gateway也成为异域网关XORgat…

Python数据可视化之图表组成元素

1.1绘制 matplotlib 图表组成元素的主要函数matplotlib 是如何组织内容的&#xff1f;在一个图形输出窗口中&#xff0c;底层是一个 Figure实例&#xff0c;我们通常称之为画布&#xff0c;包含一些可见和不可见的元素。在画布上&#xff0c;自然是图形&#xff0c;这些图形就是…

Allegro如何自动居中走线操作指导

Allegro如何自动居中走线操作指导 Allegro支持自动将走线居中到两个孔的中间,避免手动去调整的麻烦,类似下图 具体操作如下 点击Spread Between VoidsOptions选择需要居中走线的层面,并且Void clearance输入0

OpenGL ES着色器语言(GLSL ES)规范 ——上篇

文章目录前言OpenGL ES基础一段基本的着色器代码大小写和分号数据值类型、命名规范、类型转换运算符矢量和矩阵矢量和矩阵类型矢量构造、访问矩阵构造、访问矢量矩阵运算规则特殊类型—结构体和数组结构体数组取样器总结前言 着色器语言通过控制GPU来进行前端图形的渲染&#…

《深入浅出计算机组成原理》学习笔记 Day10

浮点数与定点数1. 浮点数的不精确性2. 定点数的表示3. 浮点数的表示参考1. 浮点数的不精确性 32 比特只能表示 2 的 32 次方个不同的数&#xff0c;差不多是 40 亿个。如果表示的数超过能表示总的个数&#xff0c;那么就会有两个不同的数的二进制表示是一样的。计算机就会不知…

【深度学习炼丹】不平衡样本的处理

目录&#xff1a;不平衡样本的处理一、前言二、数据层面处理方法2.1 数据扩充2.2 数据&#xff08;重&#xff09;采样2.3 类别平衡采样三、算法&#xff08;损失函数&#xff09;层面处理方法3.1 Focal Loss3.2 损失函数加权四、参考资料一、前言 在机器学习的经典假设中往往…

VMWare 移动Linux CentOS 7虚拟机后连不上网怎么办

研究hadoop的时候发现虚拟机太大了&#xff0c;于是把3台节点的虚拟机剪切粘贴到移动硬盘上&#xff0c;但是出现了上不了网的问题 VMWare 移动Linux CentOS 7虚拟机后连不上网&#xff0c;ifconfig命令只出现lo不出现有IP地址的ens33&#xff0c;jps命令也出现了jps command …

机器学习模型搭建与评估

模型搭建和评估第三章 模型搭建和评估--建模模型搭建任务一&#xff1a;切割训练集和测试集任务二&#xff1a;模型创建任务三&#xff1a;输出模型预测结果第三章 模型搭建和评估-评估模型评估任务一&#xff1a;交叉验证任务二&#xff1a;混淆矩阵任务三&#xff1a;ROC曲线…

python爬虫学习笔记-mysql数据库介绍下载安装

数据库概述 为什么要使用数据库&#xff1f; 那我们在没有学习数据库的时候&#xff0c;数据存放在json或者磁盘文件中不也挺好的嘛&#xff0c;为啥还要学习数据库&#xff1f; 文件中存储数据&#xff0c;无法基于文件直接对数据进行操作或者运算&#xff0c;必须借助python将…

IDEA搭建Finchley.SR2版本的SpringCloud父子基础项目-------Ribbon负载均衡

1.概念 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。简单的说&#xff0c;Ribbon是Netflix发布的开源项目&#xff0c;主要功能是提供客户端的软件负载均衡算法&#xff0c;将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配…

Python闭包与闭包陷阱

1 什么是闭包 在 Python 中&#xff0c;闭包是一种特殊的函数&#xff0c;它能够记住它所在的环境&#xff08;也称作上下文&#xff09;。这意味着闭包能够访问定义它的作用域中的变量。闭包通常用于封装数据和提供对外部访问的接口。 在 Python 中使用闭包有以下几点好处&a…

数据库和SQL概述

数据库和SQL概述 数据库的好处 实现数据的持久化使用完整的管理系统统一管理&#xff0c;易于查询 常用的一些名称缩写 DB&#xff1a;数据库(Database)&#xff1a;存储数据的“仓库”。它保存了一系列有组织的数据DBMS&#xff1a;数据库管理系统(Database Management Sy…

离线用户召回定时更新

3.6 离线用户召回定时更新 学习目标 目标 知道离线内容召回的概念知道如何进行内容召回计算存储规则应用 应用spark完成离线用户基于内容的协同过滤推荐 3.6.1 定时更新代码 完整代码 import os import sys # 如果当前代码文件运行测试需要加入修改路径&#xff0c;否则后面…

游戏启动器:LaunchBox Premium with Big Box v13.1

LaunchBox知道您会喜欢的功能&#xff0c;具有风格的游戏启动器&#xff0c;我们最初将 Launchbox 构建为 DOSBox 的一个有吸引力的前端&#xff0c;但它现在拥有对现代游戏和复古游戏模拟的支持。我们让您的所有游戏看起来都很漂亮。 整理您的游戏收藏 我们不仅漂亮&#xff…