P5507 机关

news2024/11/16 20:40:54

题目背景

Steve成功降落后,在M星上发现了一扇大门,但是这扇大门是锁着的

题目描述

这扇门上有一个机关,上面一共有12个旋钮,每个旋钮有4个状态,将旋钮的状态用数字1到4表示

每个旋钮只能向一个方向旋转(状态:1->2->3->4->1),在旋转时,会引起另一个旋钮也旋转一次(方向相同,不会引起连锁反应),同一旋钮在不同状态下,可能会引起不同的旋钮旋转(在输入中给出)

当所有旋钮都旋转到状态1时,机关就打开了

由于旋钮年久失修,旋转一次很困难,而且时间很紧迫,因此Steve希望用最少的旋转次数打开机关

这个任务就交给你了

输入格式

12行,每行5个整数,描述机关的状态

第i行第一个整数si​表示第i个旋钮的初始状态是si​

接下来4个整数ai,j=1,2,3,4  表示这个旋钮在状态j时旋转,会引起第ai,j​个旋钮旋转到下一个状态

输出格式

第一行一个整数n,表示最少的步数

第二行n个整数,表示依次旋转的旋钮编号

数据保证有解

输入输出样例

输入 

3 3 7 2 6
3 1 4 5 3
3 1 2 6 4
3 1 10 3 5
3 2 8 3 6
3 7 9 2 1
1 1 2 3 4
1 3 11 10 12
1 8 6 7 4
1 9 9 8 8
1 12 10 12 12
1 7 8 9 10
输出 
6
1 2 3 4 5 6

这道题一看就肯定用搜索来写,先说一下普通搜索的思路,这题第一个想到的肯定是广搜,用广搜找每一步,枚举12个按钮的可能性,中途用一个数组,记录路径,找到终点(全都为1)时,输出步数与路径

下面放一段广搜思路的代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
struct node{
	int x[13];//现在的状态
	int path[18]; //保存路径 
	int step=0;
}n;
int a[13][6];
map<long long,int> vis;
queue<node> q;
int num(int x[]){
	int res=0;
	for(int i=1;i<=12;i++)res=res*10+x[i];
	return res;
}
void bfs(){
	//起点入队
	q.push(n);
	vis[num(n.x)]=1; 
	while(q.size()){
		node t=n=q.front();
		q.pop();
		//可能转动1-12号按钮 
		for(int i=1;i<=12;i++){
			//获取转动i号按钮后的状态
			n.x[ a[i][n.x[i]]]++;
			if(n.x[ a[i][n.x[i] ] ]==5)n.x[ a[i][n.x[i] ] ]=1;
			n.x[i]++;
			if(n.x[i]==5)n.x[i]=1;
			int b=num(n.x);
			if(vis[b]==1){
				n=t;
				continue;
			}
			vis[b]=1;
			n.path[n.step++]=i;
			if(b==111111111111){//终点判断
				printf("%lld\n",n.step);
				for(int j=0;j<n.step;j++)printf("%lld ",n.path[j]);
				return;
			}
			q.push(n);
			n=t;
		}
	}
}
signed main(){
	for(int i=1;i<=12;i++)
		for(int j=0;j<5;j++)
			scanf("%lld",&a[i][j]);
	for(int i=1;i<=12;i++)n.x[i]=a[i][0];
	bfs();
}

交上去我们就会发现只AC了四个,其他全都TLE了。

那么这个时候,我们就要对代码进行优化。

双向广搜我不太推荐,因为要输出路径,双向广搜输出比较麻烦,所以这里呢就改成A*吧 

A*算法就是在所有的节点中选择最优的(最容易到达终点的),这样可以节省许多时间,就好比找东西,先去找可能性更大的,没找到再去找可能性更小的,因此需要一个估价函数,来预估现在的价值,价值更小的也就是我们的优先搜索对象了。

这里我们的价值,就是到终点距离(这道题就是步数)加上已走的步数,估价函数所估计的,就是还要的步数。

好,回归正题,所以就要用优先队列来存储值,给优先队列写一个排序规则,按照val(价值)升序排列,每次照样取队头就行了。

但是,这个估价函数不能偷懒,如果你只返回有几个不一样的值,就会发现,还有一个TLE死犟死犟的,一直A不了

这里的估价函数,得写成每个点距离1还要几步。

完整代码如下:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int h(int x[]){//求出预估值
	int cnt=0;
	for(int i=1;i<=12;i++){
		int ans=x[i];
		int s=0;
		while(ans!=1){
			ans++;
			s++;
			if(ans==5){
				ans=1;
			}
		}
		cnt+=s;
	}
	return cnt;
}
struct node{
	int x[13];//用来存当前状态
	int path[18]; //保存路径 
	int step=0;//记录步数
	int val=0;//存预估值
	friend bool operator <(node a,node b){//优先队列的排序规则
		return a.val>b.val;
	}
}n;
int a[13][6];//用于输入和带动
map<int,int>vis;//vis用来标记
priority_queue<node> q;//创建优先队列
int num(int x[]){
	int res=0;
	for(int i=1;i<=12;i++)res=res*10+x[i];//数组转化为数字
	return res;
}
void bfs(){
	//起点入队
	n.val=h(n.x)+0;//求起点的预估值
	q.push(n);//起点入队
	vis[num(n.x)]=1;//记录
	while(!q.empty()){
		node t=n=q.top();//获取队头
		q.pop();//队头出队
		//可能转动1-12号按钮 
		for(int i=1;i<=12;i++){//循环,遍历每一个按钮
			//获取转动i号按钮后的状态
			n.x[ a[i][n.x[i]]]++;//被联动的按钮做改变
			if(n.x[ a[i][n.x[i] ] ]==5)n.x[ a[i][n.x[i]] ]=1;//边界判断
			n.x[i]++;//当前按钮做改变
			if(n.x[i]==5)n.x[i]=1;//判断边界
			int b=num(n.x);//转化为数字
			if(vis[b]==1){//如果这个状态找过,直接跳过
				n=t;//返回原来状态
				continue;//跳过这次循环
			}
			vis[b]=1;//标记当前状态
			n.val=h(n.x)+n.step;//记录当前预估值
			n.path[n.step++]=i;//路径记录数组记录路径
			if(b==111111111111){//如果到达了终点,输出
				printf("%lld\n",n.step);//输出次数
				for(int j=0;j<n.step;j++)printf("%lld ",n.path[j]);//输出方法
				return;
			}
			q.push(n);//将当前状态入队
			n=t;//回到原来的值
		}
	}
}
signed main(){
	//输入
	for(int i=1;i<=12;i++)
		for(int j=0;j<5;j++)
			scanf("%lld",&a[i][j]);
	//初始化起点状态:333333111111 
	
	for(int i=1;i<=12;i++)n.x[i]=a[i][0];//取每个按钮的当前状态
	bfs();//调用函数
}

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

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

相关文章

页面router路由设计

Vue命名视图 命名视图 | Vue Router 如果要在 如何要在main区域里使用路由的话&#xff0c;整体区域是Layout&#xff0c;内涵Header和Nav以及Main path: /index,name: index,component: Layout, 若要只修改main区域的话&#xff0c;则取要加上v-if判断&#xff0c;来确实是…

小程序接入第三方信息流流程 下载SDK

由第三方信息流提供相应的SDK下载链接以及接入说明和开发文档或其他方式接入&#xff0c;如果第三方能支持小程序SDK&#xff0c;则不需要后面步骤&#xff0c;只需要提供相关开发文档和接入方式接口 接入SDK 后台开发人员接入第三方提供的SDK&#xff0c;并进行相关接口开发…

MySQL数据库的高级SQL语句与高级操作(2)

目录 一、子查询 1、语法: 2、以下例子均以图中两个表为基础 例子1&#xff1a;查询yun1班级大于85分的学生记录 例子2&#xff1a;将yun2班的学生记录放在一个单独的表中&#xff0c;叫yun2 例子3&#xff1a;教务处误把yun3班叫张丽的学生的成绩搞错了&#xff0c;应该为…

测试开发工程师(QA)职业到底需要干些什么?part5:性能测试工程师QA

工作职责 性能测试工程师&#xff08;Performance Testing Engineer&#xff09;是负责评估和优化软件、应用程序或系统在不同负载和压力条件下的性能的专业人员。他们的工作职责包括以下几个方面&#xff1a; 性能测试计划&#xff1a;性能测试工程师与开发团队、产品团队和系…

云原生最佳实践系列 4:基于 MSE 和 SAE 的微服务部署与压测

方案概述 云原生应用平台为基于 Spring Cloud / Dubbo 开发的微服务应用提供了完善的能力支撑&#xff0c;例如服务注册发现、Serverless 无服务部署、实例弹性伸缩、微服务链路跟踪、全链路压力测试等&#xff0c;应用能够方便快捷的部署在阿里云上。 阿里云原生产品完全兼容…

mysql-->highgo迁移

1、迁移工具免安装,解压双击迁移工具&#xff0c;会进入如下界面&#xff1a;migration.rar 2、新建组–>创建新的服务 3、在创建好的服务下,新建数据库连接,建立源表和目标表 4、这一步是获取源库&#xff08;Mysql数据库&#xff09;与目标库&#xff08;瀚高数据库&…

ensp配置acl高级配置访问控制列表

拓扑结构 资源已上传 acl访问控制列表 简单配置&#xff1a;控制目的ip地址 高级配置&#xff1a;源ip地址&#xff0c;目的ip地址等。 要求&#xff1a;拓扑三个vlan 10&#xff0c;20&#xff0c;30&#xff0c;通过设置acl使10网段可以访问20网段&#xff0c;但是不可以…

git最常用的命令与快捷操作说明

git最常用的命令与快捷操作说明 最常用的git三条命令1、git add .2、git commit -m "推送注释"3、git push origin 远程分支名:本地分支名 其他常用命令本地创建仓库分支删除本地指定分支切换本地分支合并本地分支拉取远程仓库指定分支代码过来合并推送代码到远程分支…

JS-16-标签函数

一、模版字符串 模版字符串&#xff0c;可以非常方便地引用变量&#xff0c;并合并出最终的字符串。 它允许你嵌入表达式&#xff0c;并通过${expression}语法来执行这些表达式。模板字符串使用反引号&#xff08;&#xff09;而不是普通的单引号或双引号。 模板字符串有几个…

工作的第二天

昨天的进度 写今天思路如何做评论表的增删该查评论表的增加 选择用户和商品 弹出框出现了问题 检查代码 结构没有问题 定义变量也没有问题 控制太中也没有报错信息 问题解决了 出现的问题在哪里定义的变量都有问题应该现在 setup 上面 定义一个 变量 const ref ref(fals…

Python爬虫如何快速入门

写了几篇网络爬虫的博文后&#xff0c;有网友留言问Python爬虫如何入门&#xff1f;今天就来了解一下什么是爬虫&#xff0c;如何快速的上手Python爬虫。 一、什么是网络爬虫 网络爬虫&#xff0c;英文名称为Web Crawler或Spider&#xff0c;是一种通过程序在互联网上自动获取…

Excel学习笔记(持续更新-20240326)

写在前面 Excel的学习心得分享&#xff0c;佛系更新。2024/03/26 目录 Excel每次都是以只读模式打开 给Excel设置“开机密码” 保护你的excel不让别人篡改 1.1Excel每次都是以只读模式打开 背景&#xff1a;如果有个工具&#xff0c;每天都有很多人使用&#xff0c;如果是…

【SpringBoot】读取配置文件

读取appliaction.properties里面的端口数据 Value方式 RestController public class getText {//value方式读取文件Value("${server.port}")private String port;GetMapping("getPort")public String getPort(){return port;} }使用ConfigurationPropert…

第4章:掌握标准提示,输出更精准

标准提示 标准提示&#xff0c;是引导ChatGPT输出的一个简单方法&#xff0c;它提供了一个具体的任务让模型完成。 如果你要生成一篇新闻摘要。你只要发送指示词&#xff1a;“汇总这篇新闻”。 提示公式&#xff1a;生成[任务] 生成新闻文章的摘要&#xff1a; 任务&#x…

【每日跟读】常用英语500句(100~200)

【每日跟读】常用英语500句 My apologies. 我向你道歉 Mayday. 求救 I’m begging you. 我求你了 Allow me. 让我来 That’s for sure. 那是肯定的 I wish I could. 我希望我能 Don’t leave me. 别离开我 You suck. 你太烂了 In that case. 这样的话 From now on. 从…

AI大模型学习——AI领域技术发展

目录 前言 一、AI大模型学习的理论基础 二、AI大模型的训练与优化 三、AI大模型在特定领域的应用 四、AI大模型学习的伦理与社会影响 五、未来发展趋势与挑战 总结 前言 在当前技术环境下&#xff0c;AI大模型学习不仅要求研究者具备深厚的数学基础和编程能力&#xff…

安达发|印染行业选择APS自动排单软件需要注意什么?

在印染行业中&#xff0c;APS&#xff08;高级计划排程系统&#xff09;自动排单软件的应用可以极大地提升生产效率、减少浪费、优化资源分配&#xff0c;并提高客户满意度。然而&#xff0c;在选择和实施APS自动排单软件时&#xff0c;企业需要注意以下几个关键点&#xff1a;…

高精密基准源 国产替代 REF191 ADR4520 ADR420 ADR430 ADR440 REF5020 MAX6126

高精密基准源 国产替代 REF191 ADR4520 ADR420 ADR430 ADR440 REF5020 MAX6126 ADR03 REF03 REF192 AD580 AD780 ADR441 ADR4525 ADR431 ADR421 REF5025ADR423 ADR433 ADR443 ADR4530 REF193 AD780 ADR06 REF5030ADR434 ADR444 ADR4540 REF198 REF5040ADR425 ADR435 ADR445 AD…

利用Python进行数据可视化Plotly与Dash的应用【第157篇—数据可视化】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 利用Python进行数据可视化Plotly与Dash的应用 数据可视化是数据分析中至关重要的一环&…

ONNX系列: ONNX模型结构解析

1. ONNX 背景 ONNX 全称为 Open Neural Network Exchange&#xff0c;是微软提出并推广的一种机器学习模型的开放格式表示。ONNX定义了一组通用的算子集、一系列用于构建深度学习模型的模块以及一种通用的文件格式&#xff0c;使得人工智能开发人员能够将模型与各种框…