C++ 2019-2022 CSP_J 复赛试题横向维度分析(下)

news2024/11/17 1:31:00

本文继续讲解第4题,第4题是压轴题,难度肯定是有的。也决定了是否能够拿到一等奖的关键题,也是区别能力高低的筛选题。

1.2022

1.1 题目

上升点列point

1.2 题目描述

在一个二维平面内,给定n个整数点(xi,yi),此外你还可以自由添加k个整数点。

你在自由添加k个点后,还需要从n+k个点中选出若个整数点并组成一个序列,使得序列中任意相邻两点间的欧几里得距离恰好为1而且横坐标、纵坐标值均单调不减,即 xi+1-xi=1,yi+1=yi 或 yi+1-yi=1,xi+1=xi 。请给出满足条件的序列的最大长度。

1.3 题目分析

直观感觉是一道类似于迷宫的试题。二维平面相当于一个矩阵,在此矩阵中,从一个点出发,查找到另一个点的最远距离。且搜索方向是确定的,要么向右,或者向上。可以使用深度搜索算法按步长值为 1查找任意两点之间的距离,然后从中找出最大长度。

因为不是所有点之间都是连续的,所以,搜索过程中是充许补点的。可以在搜索过程中出现断点后,试着向上或向右补点。本问题是求最值,也应该会想到使用动态规划。

1.4 编码实现

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

struct _pnt {
	int x,y;
} a[1005];
int n,k,ans;
int f[105][105]; //dp 数组 f[i][z] 当共补了z个点的情况下,
//到第 i 个原始点能连成的最多的点的个数

int dis(int i,int j) { //从 j 到 i 共需要补的点的个数
	return abs( a[i].x-a[j].x   ) +abs( a[i].y-a[j].y  )  -1;
}

bool cmp(_pnt p1,_pnt p2) {
	if(p1.x==p2.x) return p1.y<p2.y;
	else return p1.x<p2.x;
}

int main() {
	cin >> n >> k;
	for (int i = 1; i <= n; i ++) {
		cin >> a[i].x >> a[i].y;
	}
	sort(a+1,a+n+1,cmp); // 排序,保证状态转移顺序的无后效性
	for (int i = 1; i <= n; i++) {
		int x = a[i].x, y = a[i].y;
		for (int z = 0; z <= k; z++) {
			f[i][z] = 1;
			for (int j= 1; j <= n; j++) {
				if (i != j && a[j].x <= x && a[j].y <= y) {//保证j在i的左下
					int len = dis(i,j); // 从j到i共需要补Len个点
					if (z >= len) {
					f[i][z] = max(f[i][z],f[j][z - len] + len + 1);
						// 多了Len+1个连续的点,+1表示第i个点自己
					}
				}
			}
			ans = max(ans,f[i][z] + k - z);// 从i把剩余的k-z个点疯狂延续出去
		}
	}
	cout << ans;
	return 0;
}

2.2021

2.1 题目

小熊的果篮

2.2 题目描述

小熊的水果店里摆放着一排 n 个水果。每个水果只可能苹果或桔子,从左到右依 次用正整数 1、2、3、.....、n编号。连续排在一起的同一种水果称为一个“块”。小熊要把这一排水果挑到若干个果篮里,具体方法是:

每次都把每一个“块”中最左边的水 果同时挑出,组成一个果篮。

重复这一操作,直至水果用完。

注意,每次挑完一果篮 后,“块”可能会发生变化。比如两个苹果“块”之间的唯一桔子被挑走后,两个苹果
“块”就变成了一个“块”。

请帮小熊计算每个果篮里包含的水果。

2.3 题目分析

此题本质去重问题,可以有很多种方案,最简单的就是使用 2个数组,一个用来存储存原始数据,一个用来存储水果是否已经被选择的标志性数组。通过快慢指针选择出不重复的数据。

在这里插入图片描述

输出慢指针所指向位置的数据位置且在对应的标志位进行标记,移动快指针,如果快指针和慢指针所处位置数据不相同,则移动慢指针到快指针,且输出数据的位置。显然,这个是需要多轮去复。时间复杂度为 O(n2)。

在这里插入图片描述

另一种方案是借助一个队列,一个栈来实现。首先需要一个结构类型,用来存储存水果的类型和原来的位置。

struct Sg {
	//原来位置
	int pos;
	//水果类型
	int type; // 1 苹果 0 桔子
};

创建一个队列,把原始数据全部入队列。在队列的最后一个位置添加一个结束符号#

在这里插入图片描述

把队头数据放入栈中。

在这里插入图片描述

检查栈顶数据和队头数据是否相同,如果相同,把数据从队头拿出来后,再从除尾压入队列中。

在这里插入图片描述

如果栈顶数据和队头数据不相同,则把队头中数据压入栈中。

在这里插入图片描述

如此反复直到碰到 #符号。

在这里插入图片描述

然后输出栈中所有数据,继续从从队头中获取数据,直到队列中只剩下#符号。

在这里插入图片描述

时间复杂度可以控制中O(n)。可以遇到#号字符后,在栈中同样做一个标记。队列中的所有数据输出后,再统一输出栈中数据。

2.4 编码实现

#include <iostream>
#include <queue>
#include <stack>
using namespace std;
//水果数量
int n;
struct Sg {
	//原来位置
	int pos;
	//水果类型
	int type; // 1 苹果 0 桔子
	bool operator==(Sg & oth) {
		return this->type==oth.type;
	}
};

Sg sg[100];
//队列,可以使用数组
queue<Sg> myq;
//栈,也可以数组
stack<Sg> mys;

void init() {
	int type;
	//需要考虑 n=1 时的情况 
	for(int i=1; i<=n; i++) {
		cin>>type;
		sg[i]= {i,type };
		//数据入队列
		myq.push(sg[i]);
	}
	//添加结束符号,这里使用 -1 作为结束符号
	myq.push({-1,-1});
	//初始化栈
	mys.push(myq.front()) ;
	myq.pop();
}

void cal() {
	//遍历队列
	while(myq.size()!=1) {
		//比较队头和栈顶数据
		Sg dt=myq.front();
		Sg zd=mys.top();
		if(dt.type==-1) {
			//复制一个结束符到栈中
			mys.push( {-1,-1} );
			myq.push(dt) ;
		} else if(zd==dt  ) {
			//从队头出来,重新压入队列
			myq.push(dt);
		} else if(dt.type!=-1  ) {
			//压入栈中
			mys.push(dt);
		}
		myq.pop();
	}
}

void result() {
	stack<Sg> tmp;
	while(!mys.empty()) {
		tmp.push( mys.top() );
		mys.pop();
	}
	while(!tmp.empty()) {
		Sg sg= tmp.top();
		if(sg.type==-1) {
			cout<<endl;
		} else {
			cout<<sg.pos<<"\t";
		}
		tmp.pop();
	}
}

int main() {
	cin>>n;

	init();
	cal();
	result();
	return 0;
}

3.2020

3.1 题目

方格取数

3.2 题目描述

给定一个nm列的二维矩阵每个格子有特定的权值需要从左上角走到右下角,每次可以向上、下、右走一步,但不能重复经过同一个格子,求走过的格子的权值和最大是多少。

3.3 题目分析

此题也可以看成一个迷宫问题。使用深度搜索可以实现,但时间复杂度可能会较高,使用动态规划解决应是首选。

本题无法通过一次性动态规划是推导出所有数据。如下图所示,根据题意,红色标记的单元格中的值需要通过上、左、下三个单元格中的已知值方能推导出来。

而下方标记为黄色单元格中的值则又需要红色单元格中的值方能推导入出来,显然是出现了先有鸡还是先有蛋的悖论。破坏了动态规划的无后序性法则。

在这里插入图片描述

这里可以采用先分离出不同方向的子状态值,然后综合子状态得到最终状态的思路。

第一步:先找到动态规划的base case。对于第一列而言,因为只有一种路径可行,对第一列做前缀和操作。

在这里插入图片描述

第二步:根据 dp数组中的值由左向右推导出dpLeft数组中的状态值。已知左边的值,向右移动时,右边的值很容易推导出来。

在这里插入图片描述

第三步:根据dpLeft中的值向上,向下推导出dpUpdpDown数组中的值。

在这里插入图片描述

第四步:求解 dpLeft[i][j],dpUp[i][j],dpDown[i][j]中的最大值,填充在dp[i][j]中。

在这里插入图片描述

3.4 编码实现

#include <bits/stdc++.h>
#include <iostream>
#define ll long long int
using namespace std;
//方格
ll a[100][100];
//dp 数组
int dp[100][100],dpLeft[100][100],dpUp[100][100],dpDown[100][100];
//方格的长和宽
ll n,m;
int main() {
	cin>>n>>m;
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=m; j++) {
			cin>>a[i][j];
		}
	}
	//初始化dp 表
	for(int i=0; i<=n+1; i++) {
		for( int j=0; j<=m+1; j++ ) {
			dp[i][j]=dpLeft[i][j]=dpUp[i][j]=dpDown[i][j]=1>>30;
		}
	}
	//计算 base case
	for(int i=1; i<=n; i++) {
		if(i==1)dp[i][1]=a[i][1];
		else dp[i][1]+=dp[i-1][1]+a[i][1];
	}

	for(int j=2; j<=m; j++) {
		for(int i=1; i<=n; i++ ) {
			//子状态值 1 
			dpLeft[i][j]=dp[i][j-1]+a[i][j];
		}
		for(int i=2; i<=n; i++ ) {
			//子状态值 2 
			dpUp[i][j]= max(dpLeft[i-1][j],dpUp[i-1][j] )+a[i][j];
		}

		for(int i=n-1; i>=1; i-- ) {
			//子状态值 3 
			dpDown[i][j]= max( dpLeft[i+1][j],dpDown[i+1][j] )+a[i][j];
		}

		for( int i=1; i<=n; i++ ) {
			dp[i][j]=max( dpLeft[i][j],dpUp[i][j] );
			dp[i][j]=max( dp[i][j],dpDown[i][j] );
		}
	}

	cout<<dp[n][m];
	return 0;
}

4.2019

4.1 题目

加工零件

4.2 题目描述

凯凯的工厂正在有条不紊地生产一种神奇的零件,神奇的零件的生产过程自然也很神奇。工厂里有 n 位工人,工人们从 1~n 编号。某些工人之间存在双向的零件传送带。保证每两名工人之间最多只存在一条传送带。

如果 x号工人想生产一个被加工到第 L(L>1)阶段的零件,则所有与 x 号工人有传送带直接相连的工人,都需要生产一个被加工到第L-1 阶段的零件(但 x号工人自己无需生产第L-1 阶段的零件)。
如果 x号工人想生产一个被加工到第 1 阶段的零件,则所有与 x 号工人有传送带直接相连的工人,都需要为 x号工人提供一个原材料。

轩轩是 1 号工人。现在给出 q 张工单,第 i 张工单表示编号为 ai 的工人想生产·个第Li 阶段的零件。轩轩想知道对于每张工单,他是否需要给别人提供原材料。他知道聪明的你一定可以帮他计算出来!

4.3 题目分析

无向图最短路径问题,使用广度搜索存储 1号工人到与之相连的其它工人之间的路径。

本题相当于问:1~ai,是否存在长度为li的路径;

4.4 编码实现

/*
*1. 求出1号点到每个点的最短奇数路径,和最短偶数路径;
2. q次询问,每次询问x号工人,如果生产len阶段的零件,1号点是否需要原材料;
如果1号点存在到x号点的最短奇数路径mins,且len是奇数,且len >= mins,1号点就需要提供原材料
偶数性质同上;
*/
#include <bits/stdc++.h>
#include <queue>
using namespace std;

struct Ver {
	int to;
	int next;
};

Ver a[100];
int head[100],k=0;
queue<int> myq;
int path[100][2];
bool vis[100][2];
int n,m,t;

void addEgde(int u,int v) {
	k++;
	a[k].to=v;
	a[k].next=head[u];
	head[u]=k;
}

int main() {
	scanf("%d%d%d",&n,&m,&t);
	int x,y;
	for(int i=1; i<=m; i++) {
		scanf("%d%d",&x,&y);
		addEgde(x,y);
		addEgde(y,x);
	}
	memset(path,0,sizeof(path));
	path[1][0]=0;
	if(head[1]==0)
		path[1][0]=-1;
	myq.push(1);
	while( !myq.empty() ) {
		int u=myq.front();
		for(int i=head[u]; i!=0; i=a[i].next ) {
			int to=a[i].to;
			if( path[u][0]+1<path[to][1] ) {
				path[to][1] = path[u][0] + 1;
				if(!vis[to][1]) {
					myq.push(to);
					vis[to][1] = true;
				}
			}
			if(path[u][1]+1<path[to][0]) {
				path[to][0] = path[u][1] + 1;
				if(!vis[to][0]) {
					myq.push(to);
					vis[to][0] = true;
				}
			}
		}
		myq.pop();
	}

	int len;
	while(t--) {
		scanf("%d%d",&x,&len);
		if(path[x][len%2]<=len) printf("%s\n","Yes");
		else printf("%s\n","No");
	}
	return 0;
}

5. 小结

2021、2023题目考察了动态规划,有一定难度,2020、2019的题目相对而言较简单。

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

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

相关文章

u盘初始化后怎么恢复文件?这几步操作帮你找回

随着科技的进步和便携设备的普及&#xff0c;U盘已经成为我们日常工作和生活中不可缺少的存储介质。然而&#xff0c;在使用U盘的过程中&#xff0c;我们可能会遇到各种问题&#xff0c;其中之一就是意外的初始化导致文件丢失。本文将为大家介绍如何在U盘初始化后恢复文件的方法…

苹果mac电脑显示内存不足如何解决?

忍痛删应用、删文档、删照片视频等等一系列操作都是众多Mac用户清理内存空间的方法之一&#xff0c;悲催的是一顿“猛如虎的操作”下&#xff0c;释放出来的内存空间却少的可怜&#xff0c;原因很简单&#xff0c;这样释放内存空间是无效的。如何合理有效的清理内存空间&#x…

【yolov1】详解yolov1理论 代码

目标检测要解决的3大问题&#xff1a; 1、有没有&#xff1f; 图片中是否有要检测的物体&#xff1f;&#xff08;检测物体&#xff0c;判定前景背景&#xff09; 2、是什么&#xff1f; 这些物体分别是什么&#xff1f;&#xff08;检测到的物体是什么&#xff09; 3、在…

做外贸你的差不多可能差的很多

人们常说不想当将军的士兵不是好士兵&#xff0c;然而当不好士兵的将军一定不是一个好将军&#xff0c;我们对事情或者自我的要求衡量越低的时候&#xff0c;当以什么事情都差不多为标准的时候&#xff0c;可能我们自己也就只能最高混到差不多而已了。 就拿简单的书写来说&…

高频工业RFID读写器的主要应用

随着通信技术的迅速发展&#xff0c;RFID的应用也逐渐广泛&#xff0c;产线、零售、身份识别、金融领域、门禁安全等各个方面都有RFID的身影。其中很多应用都是以高频技术应用为主&#xff0c;下面我们就跟大家一起来了解一下&#xff0c;高频工业RFID读写器的主要应用包括哪些…

高可靠性振弦采集仪可减少对仪器维护保养

高可靠性振弦采集仪可减少对仪器维护保养 振弦采集仪是一种用于测量机械设备振动和振动频率的仪器。在现代工业中&#xff0c;振动是许多机械故障的先兆&#xff0c;因此振动监测是维护和预测设备发生故障的重要手段。高可靠性振弦采集仪可以大大减少机械设备的维护保养成本&am…

查询表中的全部列的数据

MySQL从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article/details/129334507?spm1001.2014.3001.5502 语法格式: select from * 表名; 说明: * 表示所有列 由于不写where子句&#xff0c;表示无条件&#xff0c;找到所有的行&#xff01; 准备工作:执…

阿里云 Oss 权限控制

前言 最近公司的私有 Oss 服务满了&#xff0c;且 Oss 地址需要设置权限&#xff0c;只有当前系统的登录用户才能访问 Oss 下载地址。一开始想着用 Nginx 做个转发来着&#xff0c;Nginx 每当检测当前请求包含特定的 Oss 地址就转发到我们的统一鉴权接口上去&#xff0c;但是紧…

拿到 Offer 了!深信服 17K*15

作者 | 磊哥 来源 | 公众号&#xff1a;Java中文社群 转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09; 这两年的就业情况大家是有目共睹的&#xff0c;作为一个双非院校的学生&#xff0c;能拿到深信服 Java 研发岗的工作&#xff0c;学生本人还是很满意的&…

【操作工具】IDEA创建类及已有类添加注释-详细操作

1.背景 很多开发好多时候其实不太会给类添加注释&#xff0c;尤其是已经有的类&#xff0c;上网查询&#xff0c;好多文档错误百出&#xff0c;而且不全 2.正文 2.1新建类添加注释 idea给新建类创建注释有两种方式 先写一个简单的模板 /** * description: TODO * autho…

从小白到精通,十九项案例实践丨全流程HEC-RAS 1D/2D水动力与水环境模拟

水动力与水环境模型的数值模拟是实现水资源规划、环境影响分析、防洪规划以及未来气候变化下预测和分析的主要手段。然而&#xff0c;一方面水动力和水环境模型的使用非常复杂&#xff0c;理论繁复&#xff1b;另一方面&#xff0c;免费的水动力和水环境软件往往缺少重要功能&a…

怎么查看win10分辨率?我来告诉你!

Windows 10 是一个强大的操作系统&#xff0c;可以适应各种屏幕和硬件配置。然而&#xff0c;在某些情况下&#xff0c;您可能需要查看或更改显示器的分辨率设置&#xff0c;以获得最佳的图像和屏幕显示效果。本文将介绍怎么查看win10分辨率的2种方法&#xff0c;以帮助您快速查…

MySQL 全球大会summit 2023年度 --- MySQL 高可用和灾备 (音译)

开头还是介绍一下群&#xff0c;如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, Oceanbase, Sql Server等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友…

聚观早报 | 中国队拿下亚运会电竞项目首金;B站发布68部国创片单

【聚观365】9月28日消息 中国队拿下亚运会电竞项目首金 B站发布68部国创片单 支付宝持续加大流量开放 起点有声书《宿命之环》等大作陆续上线 方程豹豹5详细配置公开 中国队拿下亚运会电竞项目首金 杭州2022年第19届亚运会官网发布公告称&#xff0c;在昨日的杭州第19届亚…

2014 款金旅牌小型客车 发动机怠速抖动、加速无力

故障现象 一辆2014款金旅牌小型客车&#xff0c;搭载JM491Q-ME发动机&#xff0c;累计行驶里程约为20万km。车主反映&#xff0c;最近该车发动机怠速抖动、加速无力&#xff0c;且经常缺少冷却液。 故障诊断 根据车主描述的故障现象&#xff0c;初步判断该车气缸垫损坏&#…

分类预测 | MATLAB实现SSA-FS-SVM麻雀算法同步优化特征选择结合支持向量机分类预测

分类预测 | MATLAB实现SSA-FS-SVM麻雀算法同步优化特征选择结合支持向量机分类预测 目录 分类预测 | MATLAB实现SSA-FS-SVM麻雀算法同步优化特征选择结合支持向量机分类预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 MATLAB实现SSA-FS-SVM麻雀算法同步优化特征选择结…

【iOS逆向与安全】插件开发之某音App直播间自动发666

1.目标 由于看直播的时候主播叫我发 666&#xff0c;支持他&#xff0c;我肯定支持他呀&#xff0c;就一直发&#xff0c;可是后来发现太浪费时间了&#xff0c;能不能做一个直播间自动发 666 呢&#xff1f;于是就花了几分钟做了一个。 2.操作环境 越狱iPhone一台 frida ma…

Java【手撕链表】LeetCode 2. “两数相加“, 图文详解思路分析 + 代码

文章目录 前言一、两数相加1, 题目2, 思路分析3, 代码 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: &#x1f4d5; JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等 &#x1f4d7; Java数据结构: 顺序表, 链表, 堆…

五、过拟合问题与正则化

一、过拟合问题 &#xff08;一&#xff09;问题的提出 过拟合问题的定义&#xff0c;以线性回归为例&#xff0c;在房价预测的数据集中&#xff0c;假设函数产生的曲线有三种情况&#xff0c;如下图&#xff1a; &#xff08;1&#xff09;欠拟合&#xff08;2&#xff09;…

保姆级 -- Zookeeper超详解

1. Zookeeper 是什么(了解) Zookeeper 是一个 分布式协调服务 的开源框架, 主要用来解决分布式集群中应用系统的一致性问题, 例如怎样避免同时操作同一数据造成脏读的问题. ZooKeeper 本质上是 一个分布式的小文件存储系统 . 提供基于类似于文件系统的目录树方式的数据存储, …