【动态规划-状态压缩dp】【蓝桥杯备考训练】:毕业旅行问题、蒙德里安的梦想、最短Hamilton路径、国际象棋、小国王【已更新完成】

news2025/2/24 5:09:58

目录

1、毕业旅行问题(今日头条2019笔试题)

2、蒙德里安的梦想(算法竞赛进阶指南)

3、最短Hamilton路径(《算法竞赛进阶指南》&模板)

4、国际象棋(第十二届蓝桥杯省赛第二场C++ A组/B组)

5、小国王(《信息学奥赛一本通》 SGU223)

1、毕业旅行问题(今日头条2019笔试题)

小明目前在做一份毕业旅行的规划。

打算从北京出发,分别去若干个城市,然后再回到北京,每个城市之间均乘坐高铁,且每个城市只去一次。

由于经费有限,小明希望能够通过合理的路线安排尽可能的省些路上的花销。

给定一组城市和每对城市之间的火车票的价钱,找到每个城市只访问一次并返回起点的最小车费花销。

注意:北京为 1 号城市。

输入格式

第一行包含一个正整数 n,表示城市个数。

接下来输入一个 n 行 n 列的矩阵,表示城市间的车票价钱。

输出格式

输出一个整数,表示最小车费花销。

数据范围

1<n≤20,包括北京
车票价格均不超过 1000 元。

输入样例:
4
0 2 6 5
2 0 4 4
6 4 0 2
5 4 2 0
输出样例:
13
说明

共 4 个城市,城市 1 和城市 1 的车费为0,城市 1 和城市 2 之间的车费为 2,城市 1 和城市 3 之间的车费为 6,城市 1 和城市 4 之间的车费为 5,以此类推。

假设任意两个城市之间均有单程票可买,且价格均在 1000 元以内,无需考虑极端情况。

思路:

经典的状态压缩求最短路问题,每个城市只有两个状态:去过或者没去过,去过则为1,没去过则为0

代码:
#include<bits/stdc++.h>

using namespace std;

int n; 

const int N=20,M=1<<20;

int w[N][N];

int f[M][N];//M表示状态的压缩,N代表最后到哪一个城市了 

int main()
{
	cin>>n;
	memset(f,0x3f,sizeof f);//每个状态为正无穷,表示还没取min 
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			scanf("%d",&w[i][j]);
		}
	}
	f[1][0]=0;//初始的状态(需要费用为0) 
	//从1开始表示北京已经去过了 (二进制表示为000.....1) 
	for(int i=1;i<1<<n;i++)//(1<<n)-1就是111....1
	//例如n==5的时候,1<<5就是100000,减去1就是11111 
	{
		for(int j=0;j<n;j++)//北京开始 
		{
			//这个状态下(终点为j,状态为i) 
			if(i>>j&1)//(i>>j表示要到第j个城市,这个状态的j位就要是1(否则到不了)) 
			{
				for(int k=0;k<n;k++)//从第k个城市转移过来
				{
					if((i-(1<<j))>>k&1)//i中减去第j个城市后还包含k
					//说明这个状态到过k,可以从k转移过来
					f[i][j]=min(f[i][j],f[i-(1<<j)][k]+w[k][j]); 
				} 
			}
		}
	}
	int res=1<<31-1;
	for(int i=1;i<n;i++)
	{
		res=min(res,f[(1<<n)-1][i]+w[i][0]);
	}
	cout<<res;
	return 0;
} 

2、蒙德里安的梦想(算法竞赛进阶指南)

求把 N×M 的棋盘分割成若干个 1×2 的长方形,有多少种方案。

例如当 N=2,M=4 时,共有 5 种方案。当 N=2,M=3,时,共有 3 种方案。

如下图所示:

2411_1.jpg

输入格式

输入包含多组测试用例。

每组测试用例占一行,包含两个整数 N 和 M。

当输入用例 N=0,M=0 时,表示输入终止,且该用例无需处理。

输出格式

每个测试用例输出一个结果,每个结果占一行。

数据范围

1≤N,M≤11

输入样例:
1 2
1 3
1 4
2 2
2 3
2 4
2 11
4 11
0 0
输出样例:
1
0
1
2
3
5
144
51205
思路:

先放置完横着放的,之后竖着放的方法就是固定的

一个重要的任务就是判断放置的方法是否合法

基本框架:

预处理:

dp:

代码:
#include<bits/stdc++.h>

using namespace std;

const int N=12;
const int M=1<<11;

int n,m;

long long  f[N][M];//第i列的状态为M ,j表示出头的方格数量 

bool st[M];//用来表示某一种状态是否合法 

int main()
{

	while(cin>>n>>m,n || m)
	{
		memset(f,0,sizeof f);
		
		//开始预处理
		for(int i=0;i<1<<n;i++)//枚举每一种状态 
		{
			int cnt=0;//记录连续的空格数量 
			st[i]=true; 
			for(int j=0;j<n;j++)
			{
				if(i>>j&1)//这个位置不是空格 
				{
					if(cnt&1)st[i]=false;//这个位置之前的连续空格数量是奇数,不合法 
					cnt=0;
				}
				else cnt++;
			}
			if(cnt&1)st[i]=false; 
		}

		f[0][0]=1;//第0列没有上一列,所以没有戳出来的
		//小方块里什么都没有放,只有这一种状态 
		
		for(int i=1;i<=m;i++)//枚举列 
		{
			for(int j=0;j<1<<n;j++)//枚举这一列的状态 
			{
				for(int k=0;k<1<<n;k++)//枚举上一列的状态 
				{
					if(((j&k)==0) && st[j|k])//(k列加上j列向后伸的格子后要合法)
					{
						f[i][j]+=f[i-1][k];
					}
				}
			}
		} 
		cout<<f[m][0]<<endl;
	}
	

	return 0;
}

3、最短Hamilton路径(《算法竞赛进阶指南》&模板)

给定一张 n 个点的带权无向图,点从 0∼n−1 标号,求起点 0 到终点 n−1 的最短 Hamilton 路径。

Hamilton 路径的定义是从 0到 n−1 不重不漏地经过每个点恰好一次。

输入格式

第一行输入整数 n。

接下来 n 行每行 n 个整数,其中第 i 行第 j 个整数表示点 i 到 j 的距离(记为 a[i,j])。

对于任意的 x,y,z,数据保证 a[x,x]=0,a[x,y]=a[y,x],并且 a[x,y]+a[y,z]≥a[x,z]。

输出格式

输出一个整数,表示最短 Hamilton 路径的长度。

数据范围

1≤n≤20
0≤a[i,j]≤1e7

输入样例:
5
0 2 4 5 1
2 0 6 5 3
4 6 0 8 3
5 5 8 0 5
1 3 3 5 0
输出样例:
18
思路:

状态压缩dp模板

代码:
#include<bits/stdc++.h>

using namespace std;

const int N=20,M=1<<20;

int n;

int w[N][N];

int f[M][N];

int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			scanf("%d",&w[i][j]);
		}
	}
	//状态压缩dp 
	memset(f,0x3f,sizeof f);
	//初始为0
	f[1][0]=0;//i==1表示第一个点已经走了,j==0表示目前在第一个点 
	//从0000.。。1开始 
	for(int i=1;i<1<<n;i++)
	{
		//从起点0开始 
		for(int j=0;j<n;j++)
		{
			//只有i包含j这个点,才能从i这个状态转移到终点为j的状态 
			if(i>>j&1)
			{
				//f[i][k]---k-j
				for(int k=0;k<n;k++)
				{
					if((i-(1<<j))>>k&1)
					{
						//(用不包含j点的状态来转移)
						f[i][j]=min(f[i][j],f[i-(1<<j)][k]+w[k][j]);
					}
				}
			}
		}
	}
	
	int res=1<<31-1;
	
	//for(int i=1;i<n;i++)
	//{
	//	res=min(res,f[(1<<n)-1][i]);
	//}
	
	//cout<<res<<endl;
	
	//标明了终点是n-1,所以说直接选终点是n-1的情况 
	cout<<f[(1<<n)-1][n-1];
	return 0;
}

4、国际象棋(第十二届蓝桥杯省赛第二场C++ A组/B组)

众所周知,“八皇后” 问题是求解在国际象棋棋盘上摆放 8 个皇后,使得两两之间互不攻击的方案数。

已经学习了很多算法的小蓝觉得 “八皇后” 问题太简单了,意犹未尽。作为一个国际象棋迷,他想研究在 N×M 的棋盘上,摆放 K 个马,使得两两之间互不攻击有多少种摆放方案。

由于方案数可能很大,只需计算答案除以 1000000007 (即 1e9+7) 的余数。

如下图所示,国际象棋中的马摆放在棋盘的方格内,走 “日” 字,位于 (x,y)格的马(可以攻击 (x+1,y+2)、(x+1,y−2)、(x−1,y+2)、(x−1,y−2)、(x+2,y+1)、(x+2,y−1)、(x−2,y+1) 和 (x−2,y−1) 共 8 个格子。

QQ截图20210512104039.png

输入格式

输入一行包含三个正整数 N,M,K分别表示棋盘的行数、列数和马的个数。

输出格式

输出一个整数,表示摆放的方案数除以 1000000007(即 1e9+7) 的余数。

数据范围

对于 5%5% 的评测用例,K=1;
对于另外 10%10% 的评测用例,K=2;
对于另外 10%10% 的评测用例,N=1;
对于另外 20%20% 的评测用例,N,M≤6,K≤5;
对于另外 25%25% 的评测用例,N≤3,M≤20,K≤12;
对于所有评测用例,1≤N≤6,1≤M≤100,1≤K≤20。

输入样例1:
1 2 1
输出样例1:
2
输入样例2:
4 4 3
输出样例2:
276
输入样例3:
3 20 12
输出样例3:
914051446
思路:
枚举思路:

代码:
#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 110,M=6,MOD=1e9+7;
int f[N][1<<M][1<<M][21];
int n,m,k;
int get_count(int x)//返回x的二进制有多少个1
{
    int res=0;
    while(x)
    {
        res++;
        x-=(x&-x);
    }
    return res;
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    f[0][0][0][0]=1;//状态初始化:第0行时,状态只能是0,只能是放0个马
    //5层循环比较乱,把图画出来,照着图写
    for(int i=1;i<=m;i++)
    {
        for(int c=0;c<1<<n;c++)
        {
            for(int a=0;a<1<<n;a++)
            {
                if((c&(a<<2))||(a&(c<<2))) continue;
                for(int b=0;b<1<<n;b++)
                {
                    if(b&(a<<2)||a&(b<<2)) continue;
                    if(b&(c<<1)||c&(b<<1)) continue;
                    int t=get_count(b);
                    for(int j=t;j<=k;j++)
                    f[i][a][b][j]=(f[i][a][b][j]+f[i-1][c][a][j-t])%MOD;//对应集合划分,枚举j,f[i-1][c][a][j-t]都能到达f[i][a][b][j]
                }
            }
        }
    }
    int res=0;
    for(int a=0;a<1<<n;a++)
    {
        for(int b=0;b<1<<n;b++)
        {
            res=(res+f[m][a][b][k])%MOD;//m,k固定,a,b随意
        }
    }
    printf("%d",res);
    return 0;
}

5、小国王(《信息学奥赛一本通》 SGU223)

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

输入格式

共一行,包含两个整数 n 和 k。

输出格式

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

数据范围

1≤n≤10,
0≤k≤n**2

输入样例:
3 2
输出样例:
16
思路:

代码:
#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 11, M = 1 << N, C = N * N;

int n, m, K;
LL f[N][C][M];
int cnt[M];
vector<int> legal_state;
vector<int> state_trans[M];

bool check(int state)
{
    return !(state & state >> 1);
}
int count(int state)
{
    int res=0;
    while(state)
    {
        res++;
        state-=state & -state;
    }
    return res;
}
int main()
{
    cin >> n >> K;
    //预处理所有合法状态
    for (int st = 0; st < 1 << n; ++ st)
        //检查当前状态是否合法
        if (check(st))
            legal_state.push_back(st),
            cnt[st] = count(st);
    m = legal_state.size();
    //预处理所有合法状态的合法转移
    for (auto cur_st: legal_state)
        for (auto to_st: legal_state)
            if (!(cur_st & to_st) && check(cur_st | to_st))//上下不相邻且纵坐标也不相邻
                state_trans[cur_st].push_back(to_st);
    //动态规划
    f[0][0][0] = 1;
    for (int i = 1; i <= n; ++ i)
        for (int j = 0; j <= K; ++ j)
            for (auto &state: legal_state)
                for (auto &pre_st: state_trans[state])
                    if (j - cnt[state] >= 0)
                        f[i][j][state] += f[i - 1][j - cnt[state]][pre_st];
    //统计目标状态的所有方案数
    LL res = 0;
    for (auto state: legal_state) res += f[n][K][state];
    cout << res << endl;
    return 0;
}

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

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

相关文章

MySQL的基本查询

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;MySQL &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容介绍了mysql的基本查询部分的知识&#xff0c;包括Crea…

日期时间相关的类

分界线jdk8 jdk8之前和之后分别提供了一些日期和时间的类&#xff0c;推荐使用jdk8之后的日期和时间类 Date类型 这是一个jdk8之前的类型&#xff0c;其中有很多方法已经过时了&#xff0c;选取了一些没有过时的API //jdk1.8之前的日期 Date Date date new Date(); // 从1970年…

多输入多输出 | Matlab实现OOA-BP鱼鹰算法优化BP神经网络多输入多输出预测

多输入多输出 | Matlab实现OOA-BP鱼鹰算法优化BP神经网络多输入多输出预测 目录 多输入多输出 | Matlab实现OOA-BP鱼鹰算法优化BP神经网络多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 多输入多输出 | Matlab实现OOA-BP鱼鹰算法优化BP神经网络…

白色磨砂质感html5页源码

白色磨砂质感html5页源码&#xff0c;简约的基础上加上了团队成员&#xff0c;自动打字特效音乐播放器存活时间 源码下载 https://www.qqmu.com/2980.html

实战搭建网易有道的QAnything(一) 前提准备工作

前言&#xff1a; 早上地铁上刷到了关于有道的QAnything的介绍&#xff0c;刚好也有搭建一个知识库的想法&#xff0c;既然有想法那就干起来&#xff0c;电脑的操作系统用的win11&#xff0c;显卡用了两块4060。 一、安装windows子系统 1. 开始-》运行-》控制面板 打开原始的控…

开启Java之旅——用Java实现简易的图书管理系统(24.4.7)

图书管理系统 一、设计思路 1、首先需要区分两类人&#xff0c;图书管理员和借书用户&#xff0c;不同的用户要展现不同的界面&#xff0c;利用继承和多态可以将其实现。 2、要将不同的操作封装起来&#xff0c;单独设计成为一个类&#xff0c;为了规范实现&#xff0c;需要…

【CicadaPlayer】demuxer_service中DASH的简单理解

DASH协议 dash 是属于demuxer模块的 MPEG-DASH是一种自适应比特率流技术,可根据实时网络状况实现动态自适应下载。和HLS, HDS技术类似, 都是把视频分割成一小段一小段, 通过HTTP协议进行传输,客户端得到之后进行播放;不同的是MPEG-DASH支持MPEG-2 TS、MP4(最新的HLS也支持…

【IPV6】--- IPV6过渡技术之6 over 4隧道配置

1. IPV4和IPV6有什么区别&#xff1f; 2. IPV6如何在设备上配置&#xff1f; 3. IPV4和IPV6如何跨协议实现通信&#xff1f; 1. IPV4和IPV6 --- IPV6技术 - IP协议第六版 - 128位二进制数 - 2^12843亿*43亿*43亿*43亿 --- IPV4技术 - IP协议第四版 - 192.1…

element-ui使用记录

element-ui的组件名就是类名 样式穿透&#xff08;用来修改没有类名的子组件样式&#xff09; 例如修改头部具名插槽的样式&#xff08;但是无法定位该元素&#xff09; 查看最后生成的html结构中对应的结构&#xff08;这里的头部有类名&#xff0c;可以直接对该类名进行样…

C#学习笔记9:winform上位机与西门子PLC网口通信_上篇

今日继续我的C#学习笔记&#xff0c;今日开始学习打开使用千兆网口来进行与西门子PLC的通信&#xff1a; 文章提供整体代码、解释、测试效果截图、整体测试工程下载&#xff1a; 主要包含的知识有&#xff1a;下载NuGet程序包、西门子PLC及通信协议、搭建虚拟的S7通信仿真环境…

Betaflight 4.5RC3 AT32F435遇到的一些“怪”现象

Betaflight 4.5RC3 AT32F435遇到的一些“怪”现象 1. 源由2. “怪”现象2.1 电机#4没有RPM转速2.2 遥控器通道10接收机测试失败2.3 OSD 异常2.4 磁力计数据无法获取 3. 参考资料 1. 源由 升级下固件&#xff0c;追下“时髦”&#xff0c;赶下“潮流”&#xff0c;本着“活着就…

【Linux ARM 裸机】开发环境搭建

1、Ubuntu 和 Windows 文件互传 使用过程中&#xff0c;要频繁进行 Ubuntu 和 Windows 的文件互传&#xff0c;需要使用 FTP 服务&#xff1b; 1.1、开启 Ubuntu 下的 FTP 服务 //安装 FTP 服务 sudo apt-get install vsftpd //修改配置文件 sudo vi /etc/vsftpd.conf//重启…

ES入门十五:分页的三驾马车【from+size、search after、scroll api】

从数据集中获取数据时分页是绕不开的操作&#xff0c;一下子从数据集中获取过多的数据可能会造成系统抖动、占用带宽等问题。特别是进行全文搜索时&#xff0c;用户只关心相关性最高的那个几个结果&#xff0c;从系统中拉取过多的数据等于浪费资源。 ES提供了3种分页方式&…

2024/4/1—力扣—主要元素

代码实现&#xff1a; 思路&#xff1a;摩尔投票算法 int majorityElement(int *nums, int numsSize) {int candidate -1;int count 0;for (int i 0; i < numsSize; i) {if (count 0) {candidate nums[i];}if (nums[i] candidate) {count;} else {count--;}}count 0;…

【Redis 知识储备】冷热分离架构 -- 分布系统的演进(5)

冷热分离架构 简介出现原因架构工作原理技术案例架构优缺点 简介 引入缓存, 实行冷热分离, 将热点数据放到缓存中快速响应 (如存储到 Redis中) 出现原因 海量的请求导致数据库负载过高, 站点响应再读变慢 架构工作原理 多了缓存服务器, 对于热点数据全部到缓存中, 不常用数…

软考高级:计算机网络概述

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

24.4.7周报

星期一&#xff1a; 再学kmp&#xff0c;学的最明白的一次 贴道kmp的题 洛谷传送门 思路&#xff1a;答案为n-ne【n】&#xff0c;把字符串画两遍理解一下 思路&#xff1a;最长周期&#xff0c;复制一遍过后要求覆盖原字符串&#xff0c;及字符串中…

OpenAI Sora:浅析文生视频模型Sora以及技术原理简介

一、Sora是什么&#xff1f; Sora官方链接&#xff1a;https://openai.com/sora 视频模型领头羊Runway Gen 2、Pika等AI视频工具&#xff0c;都还在突破几秒内的连贯性&#xff0c;而OpenAI&#xff0c;已经达到了史诗级的纪录。 OpenAI&#xff0c;永远快别人一步&#xff0…

Android 11属性系统初始化流程

在init进程启动的第二阶段&#xff0c;调用PropertyInit 对属性系统进行初始化 int SecondStageMain(int argc, char** argv) {//省略PropertyInit();//省略 }PropertyInit函数在system\core\init\property_service.cpp 中实现 void PropertyInit() {//省略mkdir("/dev/…

《云原生安全攻防》-- 云原生应用风险分析

为了满足每位朋友的学习需求&#xff0c;并且支持课程的持续更新&#xff0c;本系列课程提供了免费版和付费视频版两种方式来提供课程内容。我们会持续更新课程内容&#xff0c;以确保内容的度和实用性。 在本节课程中&#xff0c;我们将一起探讨云原生应用在新的架构模式下可能…