每日一练2023.4.17-2023.4.18

news2024/10/5 14:01:45

数轴上的bfs

农夫约翰被通知,他的一只奶牛逃逸了!所以他决定,马上出发,尽快把那只奶牛抓回来.

    他们都站在数轴上.约翰在N(0≤N≤100000)处,奶牛在K(0≤K≤100000)处.约翰有

两种办法移动,步行和瞬移:步行每秒种可以让约翰从x处走到x+1或x-1处;而瞬移则可让他在1秒内从x处消失,在2x处出现.然而那只逃逸的奶牛,悲剧地没有发现自己的处境多么糟糕,正站在那儿一动不动.

    那么,约翰需要多少时间抓住那只牛呢?

输入格式

* Line 1: Two space-separated integers: N and K

    仅有两个整数N和K.

输出格式

* Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.

    最短的时间.

样例

输入样例:

5 17
Farmer John starts at point 5 and the fugitive cow is at point 17.

输出样例:

4
OUTPUT DETAILS:

The fastest way for Farmer John to reach the fugitive cow is to
move along the following path: 5-10-9-18-17, which takes 4 minutes.

 广搜 - -队列

每次取队头元素出队列,对于该队头节点,可能就是要求的节点,成功,退出;也可能不是,不是的话,利用该队头元素扩展与该节点有边相连且没有被访问的节点,将新的节点入队 ,直到队为空,所有图中相连的节点都被访问过。

 使用队列:

手写队列,队列有两个指针-front和rear,对于这两个指针,操作都是+1就是上移,如果需要构造循环队列,则需要进行取余对队列长度queueLength进行操作,队列为空等价于front不等于rear,即队首队尾指针不同,稍微整理代码如下,

///普通队列
    #define MAXLENGTH 100000
    int que[MAXLENGTH + 50];

    int rear = 0;
	int front = 0;

    while (rear != front){

        que[rear] = 入队元素值;
		rear++;
        //出队
        front = front + 1;
}

进行循环队列
	#define MAXLENGTH 100000
    int que[MAXLENGTH];

    int rear = 0;
	int front = 0;

    while (rear != front){

        que[rear] = 入队元素值;
		rear=(rear+1)%MAXLENGTH;
        //出队
        front = (front + 1)%MAXLENGTH;
}

参考代码:

#include <stdio.h>
#define MAXLENGTH 100000
int que[MAXLENGTH + 50];
int flag[MAXLENGTH + 50];
int main() {
	//int dp[MAXLENGTH+50];

	int rear = 0;
	int front = 0;
	
	int s, t;
	scanf("%d %d", &s, &t);
	que[0] = s;
	//front=(front+1)%(MAXLENGTH+50);
	rear = rear + 1;
	flag[s] = 1;
	int i = s;
	int cnt = 0;
	while (rear != front) {
		if (flag[t] == 1) {
			printf("%d\n", cnt);
			return 0;
		}
		cnt++;//步数加一

		int loopf = front;
		int loopr = rear;
		for (int j = loopf; j != loopr; j++)
		{
			int tt = que[j];
			//在范围内且没有走过 
			if (tt * 2 <= MAXLENGTH && flag[tt * 2] == 0) {
				
				que[rear] = tt * 2;
				flag[tt * 2] = 1;rear++;
			}
			if (tt + 1 <= MAXLENGTH && flag[tt + 1] == 0) {
				
				que[rear] = tt + 1;
				flag[tt + 1] = 1;rear++;
			}

			if (tt - 1 >= 0 && flag[tt - 1] == 0) {
				
				que[rear] = tt - 1;
				flag[tt - 1] = 1;rear++;
			}
			front = front + 1;
		}


	}

	return 0;
}

如果不仅要输出所需时间,还需要输出路径,如何编程实现

设置每个点的前驱并进行记录

/*
Time Limit: 1000 ms
Memory Limit: 256 mb
农夫John的奶牛跑路了。将地图视作一条数轴,
John的初始位置在s而奶牛的位置在t(0<=s,t<=100000)。John可以花费一分钟的时间使自己作如下移动:

1 从点x移动到点x+1
2 从点x移动到点x-1
3 从点x移动到点x*2
奶牛的位置一直在点t。现在给定s,t,要求John要追上奶牛最少需要几分钟。
*/

#include <stdio.h>
#define MAXLENGTH 100000//设置最大的数
int que[MAXLENGTH + 50];//记录队列,用于bfs广度优先搜索
int flag[MAXLENGTH + 50];//记录是否走过,1表示走过,0表示未走过
int mapp[MAXLENGTH + 50];//记录前驱
int pathp[MAXLENGTH + 50];//记录路径,用于输出路径
int main() {
	//队尾指针
	int rear = 0;
	//队首指针
	int front = 0;
	
	int s, t;
	scanf("%d %d", &s, &t);
	que[0] = s;//起点入队
	//front=(front+1)%(MAXLENGTH+50);
	rear = rear + 1;//尾指针移动
	flag[s] = 1;//标记,该点已走过
	int cnt = 0;//计数,当前所走时间
	while (rear != front) {
		if (flag[t] == 1) {
			//到达终点,输出时间和路径
			//输出时间
			printf("%d\n", cnt);
			//路径转换--记录是前驱,需要先得到路径再逆序输出
			int tmp;
			tmp = t;
			//printf("%d<-", tmp);
			int itmp = 0;
			pathp[itmp] = tmp;
			itmp++;
			while (1) {
				if (mapp[tmp] == s)
				{
					//printf("%d", mapp[tmp]);
					pathp[itmp] = mapp[tmp];
					//itmp++;
					break;
				}
				else {
					//printf("%d<-", mapp[tmp]);
					pathp[itmp] = mapp[tmp];
					itmp++;
					tmp= mapp[tmp];
				}
			}
			//输出起点
			printf("%d", pathp[itmp]);//print s
			//输出路径,直到终点
			for (int j = itmp-1; j >= 0; j--) {
				printf("->%d", pathp[j]);//print s
			}
			return 0;
		}
		cnt++;//步数加一
		//记录当前队列队首队尾指针
		int loopf = front;
		int loopr = rear;
		//当前队列数据出队并压入新的数据
		for (int j = loopf; j != loopr; j++)
		{
			int tt = que[j];
			//在范围内且没有走过 
			if (tt - 1 >= 0 && flag[tt - 1] == 0) {

				que[rear] = tt - 1;//入队
				flag[tt - 1] = 1;//标记
				mapp[tt - 1] = tt;//前驱
				rear++;//入队
			}
			if (tt * 2 <= MAXLENGTH && flag[tt * 2] == 0) {
				
				que[rear] = tt * 2;//入队
				flag[tt * 2] = 1;//标记
				mapp[tt * 2] = tt;//前驱
				rear++;//入队
			}
			if (tt + 1 <= MAXLENGTH && flag[tt + 1] == 0) {
				
				que[rear] = tt + 1;//入队
				flag[tt + 1] = 1;//标记
				mapp[tt + 1] = tt;//前驱
				rear++;//入队
			}
			front = front + 1;//出队
		}
	}
	return 0;
}

二维平面上的bfs

定义一个二维数组:

int maze[5][5] = {

0, 1, 0, 0, 0,

0, 1, 0, 1, 0,

0, 0, 0, 0, 0,

0, 1, 1, 1, 0,

0, 0, 0, 1, 0,

};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

输入:一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
输出:左上角到右下角的最短路径,格式如样例所示。
样例输入:

0, 1, 0, 0, 0,

0, 1, 0, 1, 0,

0, 0, 0, 0, 0,

0, 1, 1, 1, 0,

0, 0, 0, 1, 0,

复制
样例输出:
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

提示:

在一个点访问完后,并且拓展出其周围全部的点后,并不能就丢弃,

而是应该储存起来;
然后通过下标,回溯寻找出路径。

输出路径,可以参考链表或者迪杰斯特拉算法等,对于一个点,设置其前继,即该点前面的点,由此可以得到路径。

#include<stdio.h>
int maze[10][10];
struct point {
	int x;
	int y;
};
struct point que[100];
int flag[10][10];//记录是否走过 
struct point  mapp[10][10];//记录(i,j)的前驱 
struct point path[100];//记录路径用于输出 

int main() {
	for (int i = 0; i < 5; i++)
		for (int j = 0; j < 5; j++) {
			scanf("%d,", &maze[i][j]);
		}
	int front = 0;
	int rear = 0;
	que[0].x = 0;//入队 
	que[0].y = 0;
	rear++;
	flag[0][0] = 1;//左上角点标记 
	int cnt = 0;
	while (1) {
		if (flag[4][4] == 1) {//到达终点 
			printf("路径长度是%d\n", cnt);
			//路径转换并输出 
			int pathcnt = 0;
			//path[0].x = 4;
			//path[0].y = 4;
			//pathcnt++;
			struct point pointtmp;
			pointtmp.x = 4;
			pointtmp.y = 4;

			while (1) {
				int tmppathx = pointtmp.x;
				int tmppathy = pointtmp.y;
				if (tmppathx == 0 && tmppathy == 0) {
					//到达起点 
					path[pathcnt].x = 0;
					path[pathcnt].y = 0;
					break;
				}
				else {//迭代 
					path[pathcnt].x = tmppathx;
					path[pathcnt].y = tmppathy;
					pathcnt++;//下标加一 
					pointtmp.x = mapp[tmppathx][tmppathy].x;
					pointtmp.y = mapp[tmppathx][tmppathy].y;
				}
			}
			//输出起点
			for (int printi = pathcnt; printi >= 0; printi--) {
				printf("(%d,%d)\n", path[printi].x, path[printi].y);
			}
			break;
		}
		cnt++;
		int rear_ = rear;
		int front_ = front;
		for (int i = front_; i != rear_; i++) {
			//寻找可能入队的
			int xtmp = que[i].x;
			int ytmp = que[i].y;
			int next[4][2] = { 1,0,0,1,-1,0,0,-1
			};
			for (int nexti = 0; nexti < 4; nexti++) {
				int nextx = xtmp + next[nexti][0];
				int nexty = ytmp + next[nexti][1];
				if (nextx < 5 && nexty < 5 && nextx >= 0 && nexty >= 0 && maze[nextx][nexty] == 0 && flag[nextx][nexty] == 0) {
					que[rear].x = nextx;//入队 
					que[rear].y = nexty;
					rear++;
					flag[nextx][nexty] = 1;//标记 
					mapp[nextx][nexty].x = xtmp;//记录前驱 
					mapp[nextx][nexty].y = ytmp;
				}
			}
			front++;//出队 
		}
	}
	return 0;
}

bfs

 如图所示: 有9只盘子,排成1个圆圈。其中8只盘子内装着8只蚱蜢,有一个是空盘。


我们把这些蚱蜢顺时针编号为 1~8。每只蚱蜢都可以跳到相邻的空盘中,也可以再用点力,越过一个相邻的蚱蜢跳到空盘中。
请你计算一下,如果要使得蚱蜢们的队形改为按照逆时针排列,并且保持空盘的位置不变(也就是1-8换位,2-7换位,...),至少要经过多少次跳跃? 

思路:多动不如一动,考虑空盘子在动,

盘子的状态使用数字表示,数字有很多,9*8*7*6*5*4*3*2*1种排列情况,但是使用数字直接表示需要更多的数据内存,会报错,使用map完成映射,缩小数组元素个数;其余就是bfs常规部分,代码如下,

#include<stdio.h>
#include <map>
#include <iostream>
#include <algorithm>
#define MAXSIZE 654321

struct point {
	int x[10];
};
#define MAXNUM 9
int que[MAXSIZE];
int flag[MAXSIZE];//记录是否走过  

using namespace std;
map<int,int> mp;

int main() {

	int rear = 0;
	int front = 0;
	struct point init;
	for (int i = 0; i < MAXNUM; i++) {
		init.x[i] = i;
	}
	struct point expo;
	expo.x[MAXNUM-1] = 1;
	for (int i = MAXNUM-2; i >= 0; i--) {
		expo.x[i] = expo.x[i+1] * 10;
	}
	int flagNum = 0;
	for (int i = 0; i < MAXNUM; i++) {
		flagNum += i * expo.x[i];
	}
	int endNum = 0;
	for (int i = 0; i < MAXNUM; i++) {
		endNum += i * expo.x[MAXNUM-i];
	}

	//实现映射
	//87654321->8*7*6*5*4*3*2*1
	int a[MAXNUM];
	for (int i = 0; i < MAXNUM; i++) {
		a[i] = i;
	}
	int mulRes = 1;
	int uppernum = MAXNUM;
	//printf("%d\n", uppernum);
	for (int i = 1; i <= uppernum; i++)
		mulRes = mulRes * i;
	//printf("%d", mulRes);
	for (int i = 0; i < mulRes; i++) {
		int sum = 0;
		for (int j = 0; j < MAXNUM; j++)
			sum += a[j] * expo.x[j];
		mp[sum] = i;
		next_permutation(a, a + MAXNUM);
	}


	//队列操作
	que[0] = flagNum;
	rear++;
	flag[mp[flagNum]] = 1;//标记 
	int cnt = 0;
	while (1) {
		//87654321--9
		if (flag[mp[endNum]] == 1) {
			printf("%d\n", cnt);
			break;
		}
		else {
			cnt++;
			int front_ = front;
			int rear_ = rear;
			for (int i = front_; i != rear_; i++) {
				int tempPointNum = que[i];
				//printf("%d\n", tempPointNum);
				struct point pointNow;
				int pos0;
				//数字转换为数组 
				for (int j = 0; j < MAXNUM; j++) {
					//printf("%d %d\n", j, tempPointNum / expo.x[j]);
					pointNow.x[j] = tempPointNum / expo.x[j];
					if (pointNow.x[j] == 0)pos0 = j;//找到位置 
					tempPointNum= tempPointNum- pointNow.x[j]* expo.x[j];
				}

				//数组变换,得到新的数
				int nextOp[4] = { 1,-1,2,-2 };
				for (int transi = 0; transi < 4; transi++) {
					//struct point pointNow;
					int trans2 = (pos0 + nextOp[transi] + MAXNUM) % MAXNUM;
					int arr2num = 0;
					for (int numi = 0; numi < MAXNUM; numi++) {
						if (numi == trans2) {
							arr2num += pointNow.x[pos0] * expo.x[numi];
							continue;
						}
						if (numi == pos0) {
							arr2num += pointNow.x[trans2] * expo.x[numi];
							continue;
						}
						arr2num += pointNow.x[numi] * expo.x[numi];
					}

					if (flag[mp[arr2num]] == 0) {
						que[rear] = arr2num;
						rear++;//入队 
						flag[mp[arr2num]] = 1;
					}
				}
				front++;//出队 
			}
		}
	}


	return 0;
}

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

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

相关文章

门控循环神经网络学习笔记

在介绍门控循环神经网络之前&#xff0c;先简单介绍循环神经网络的基本计算方式&#xff1a; 循环神经网络之称之为“循环”&#xff0c;因为其隐藏状态是循环利用的&#xff1a; 上一次输入计算出的隐藏状态与当前的输入结合&#xff0c;得到当前隐藏状态。 cur_output, cur…

【嵌入式笔/面试】嵌入式软件基础题和真题总结——操作系统

在学习的时候找到几个十分好的工程和个人博客&#xff0c;先码一下&#xff0c;内容都摘自其中&#xff0c;有些重难点做了补充&#xff01; 才鲸 / 嵌入式软件笔试题汇总 嵌入式与Linux那些事 阿秀的学习笔记 小林coding 百问网linux 嵌入式软件面试合集 2022年春招实习十四面…

电脑丢失的dll文件怎么一键修复?修复dll方法分享

电脑丢失的dll文件怎么一键修复&#xff1f;电脑状况常常让人遇到各种问题&#xff0c;其中“DLL文件丢失”是最常见的问题之一。在这篇文章中&#xff0c;我们会介绍为何会出现DLL文件丢失的问题&#xff0c;以及提供一种简单、快捷的DLL文件修复方法。 一.为何会出现DLL文件丢…

vue使用vue-mapvgl实现烟台市各区县行政区绘制、三维柱状图

一、效果展示 二、地图组件&#xff1a; vue-mapvgl https://docs.guyixi.cn/vue-mapvgl/#/ 三、代码 main.js //vue-mapvGL import VueBMap from vue-bmap-gl; import vue-bmap-gl/dist/style.css import VueMapvgl from vue-mapvgl; Vue.use(VueBMap); Vue.use(VueMapvg…

c++算法——算法章节-时间空间复杂度

算法开章咯 这次是csp-j组算法 枚举法常用排序合集hash一维前缀和vector结构体queuestack贪心-简单贪心区间递归二分setmap二叉树图的遍历-邻接矩阵迷宫问题-dfs-深度优先搜素bfs-广度优先搜索动态规划-简单动态规划-01背包动态规划-背包-多重背包二分答案 算法是什么嘛&…

腾讯云轻量4核8G12M应用服务器带宽、月流量详细性能评测

腾讯云轻量4核8G12M应用服务器带宽&#xff0c;12M公网带宽下载速度峰值可达1536KB/秒&#xff0c;折合1.5M/s&#xff0c;每月2000GB月流量&#xff0c;折合每天66GB&#xff0c;系统盘为180GB SSD盘&#xff0c;地域节点可选上海、广州或北京&#xff0c;4核8G服务器网来详细…

0基础同学如何快速入门学Python

转自&#xff1a;https://www.zhihu.com/question/596253606/answer/2994169972 想学Python的小伙伴&#xff0c;这里给你们汇总了&#xff1a;学习资源、平台、小白环境配置、相关课程、书籍资料&#xff01;并且&#xff0c;附送学习方法以及计划制定。 一、可以了解到Pyth…

Appuploader证书申请教程

转载&#xff1a;IOS证书制作教程 点击苹果证书 按钮 点击新增 输入证书密码&#xff0c;名称 这个密码不是账号密码&#xff0c;而是一个保护证书的密码&#xff0c;是p12文件的密码&#xff0c;此密码设置后没有其他地方可以找到&#xff0c;忘记了只能删除证书重新制作&…

还在精神内耗?还在焦虑?可以看看这个

作为一个即将毕业的本科生&#xff0c;总是会不由自主的焦虑。因为不考研&#xff0c;所以显得和同学们格格不入&#xff0c;每天都在进行精神内耗&#xff0c;但是我不经意间看到了一个东西-《邓宁克鲁格效应》 上述的四个阶段刻画出了一条典型的“大师养成之路”。但大师毕竟…

华为三层交换机命令集合,已经分好类了,网工建议收藏!

你好&#xff0c;这里是网络技术联盟站。 本文给大家带来的是华为三层交换机的命令集合&#xff0c;我已经分好类&#xff0c;大家可以收藏备用&#xff01; 一、系统管理命令 1.1 查看版本信息 display version此命令用于查看交换机的版本信息&#xff0c;包括交换机的软件…

【AI理论学习】深入理解Prompt Learning和Prompt Tuning

深入理解Prompt Learning和Prompt Tuning 背景Prompt Learning简介1. Prompt是什么&#xff1f;2. 为什么要使用Prompt&#xff1f;3. Prompt Learning的形式&#xff08;举例&#xff09;4. 有哪些Pre-training language model&#xff1f;5. 常见的Prompt Learning的方法 Pro…

WebRTC 源码分析——Android 视频硬件编码

作者&#xff1a;DevYK 1. 简介 本文将重点介绍在 Android 平台上&#xff0c;WebRTC 是如何使用 MediaCodec 对视频数据进行编码&#xff0c;以及在整个编码过程中 webrtc native 与 java 的流程交互。 本篇开始会先回顾一下 Andorid MediaCodec 的概念和基础使用&#xff0…

Node【Global全局对象】之【Process】

文章目录 &#x1f31f;前言&#x1f31f;Process&#x1f31f;process属性&#x1f31f;process.env &#x1f31f;process方法&#x1f31f;process事件&#x1f31f;uncaughtException &#x1f31f;写在最后 &#x1f31f;前言 哈喽小伙伴们&#xff0c;新的专栏 Node 已开…

VSCode + GCC编译器(MinGW)开发环境中文字符乱码问题踩坑与解决办法

文章目录 问题背景问题描述测试代码测试结果现象描述问题分析 解决方案修改默认配置1. 已经存在的文件全部使用gbk编码重新保存。2. 在工程目录下新建.vscode目录&#xff0c;如果已存在则跳过此步骤。3. 在.vscode目录中新建settings.json&#xff0c;launch.json两个文件&…

SAP CAP篇二:为Service加上数据库支持

在篇一快速创建一个Service&#xff0c;基于Java的实现中&#xff0c;可见使用SAP CAP &#xff08;Cloud Programming Model&#xff09;确实可以提高开发效率。尤其是Java技术栈上&#xff0c;对比于之前使用Olingo框架来实现oData&#xff0c;使用SAP CAP真的可以做到指数级…

Hightopo应邀参加 2023 第十届中国工业数字化论坛

3 月 30 日&#xff0c;以“加快数字化转型&#xff0c;助推高质量发展”为主题的第十届中国工业数字化论坛在北京隆重举行。厦门图扑软件科技有限公司&#xff08;以下简称“图扑软件”&#xff09;应邀参展&#xff0c;与诸位专家、领导、业界同仁共同研讨工业领域的数字化创…

红包算法关于---随机分发和平均分发

目录 群发普通红包 流程图 MainRedPacket类 Manager类 Member类 User类 群发普通红包 题目介绍 某软件有多名用户&#xff08;User类&#xff09;&#xff0c;某群聊中有群主&#xff08;Manager类&#xff09;和多名普通成员&#xff08;Member类&#xff09;&#x…

c++ 11 auto的概念和用法

目录 auto的概念&#xff1a; 使用auto声明变量的语法: auto关键字使用场景: 1.简化代码的书写和阅读 2.避免类型繁琐的重复定义 auto使用时的注意事项&#xff1a; auto的概念&#xff1a; 在C11标准中&#xff0c;auto是一种类型推导机制。它可以让编译器根据右值表达式…

代码随想录训练营day52|300、最长递增子序列;674、最长连续递增序列;718、最长重复子数组

300、最长递增子序列 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子…

【Spring Boot】SpringBoot 优雅整合Swagger Api 自动生成文档

文章目录 前言一、添加 Swagger 依赖二、创建接口类三、添加 Swagger 配置类四、访问 Swagger 页面五、整合一个更友好的UI接口文档 Knife4j1、添加 Knife4j 依赖2、添加 Knife4j 配置类3、访问 Knife4j 页面 总结 前言 Swagger 是一套 RESTful API 文档生成工具&#xff0c;可…