北航2023年机试题2

【问题描述】老鼠找食物,但是回家的时候找到最短路径,输入是x-y,x是1234其中一个,代表四个方向,y是向这个方向走的距离,比如:格式:数字-数字,0-0表示找到了,1-2表示向上走两步,2-3表示向下走3步,3-1表示向左走1步,4-2表示向右走两步,0-0表示找到了。

【要求】然后返回的时候,找到最短路径,然后要求给他找回头路,把重复的路给去掉,题目首先规定四个方向:1,2,3,4分别代表上下左右,输入序列形式为1-3,3-4.....,前一个数字代表方向,后一个数字代表前进距离,以0-0为结束,结束则代表老鼠找到了食物。

        老鼠在碰到死路时会原路返回到分叉路口,探索下一个方向。需要求解老鼠原路返回的最佳路径,以2-3,4-2.....等作为输出。最佳路径的描述是“不走回头路”,即没有折返过程即可。

示例1:输入:

1-1 3-1 1-1 2-1 4-2 1-2 4-1 1-1 2-1 3-1 1-1 0-0

输出:

2-3 3-1 2-1

示例2:输入:1-10 0-0

输出:2-10

示例3:

输入:1-1 4-1 1-1 4-1 3-1 1-1 2-1 4-2 1-1 0-0

输出:2-1 3-1 2-1 3-1 2-1 3-1 2-1 

代码思路:创建结构体存储每一步的全部动作,包括方向和步数,创建一个函数用来找到最短路径,用栈存储动作序列,判断动作方向与栈顶动作是否一致进行路径简化,最后倒序出站即为最终序列。

核心逻辑:通过将栈顶动作的方向当前动作的方向进行比较,如果相同则合并步数,若不相反则直接压入栈中,若相反则进行减法操作。这样,简化完成后的路径就是一条没有折返过程的最佳路径。两个容器一个栈(元素是一整个数组)。最最核心:代入的基本单位为整个结构体(类似于结构体数组,但这里初始化是结构体容器

#include<bits/stdc++.h>
using namespace std;
bool panduan=true;
struct Action{
	int direction;
	int steps;
};
vector<Action> shortest(vector<Action> p){//求最短路径的算法,直接返回一个结构体容器 
	stack<Action> s;//用栈存储动作序列 
	for(int i=0;i<p.size();i++){//将整个容器元素全部传入进行判断 
		Action point= p[i];//获取当前动作
		if(s.empty()){
			s.push(point);//如果栈为空,直接将该点压入栈中 
		}else{
			Action top=s.top();//获取栈顶动作,以上操作的基本单位均是结构体
			//如果当前动作与栈顶动作方向相反
			if((point.direction==1&&top.direction==2)||(point.direction==2&&point.direction==1)||(point.direction==3&&point.direction==4)||(point.direction==4&&point.direction==3)){
				//相减或者相消
				if(point.steps==top.steps){
					s.pop();//方向相反步数一样,可以认定为没有改变位置 
				}else if(point.steps>top.steps){//与栈顶方向相反,走的路比栈顶元素多,重新更新栈顶方向和大小 
					point.steps-=top.steps;
					s.pop();//出栈
					s.push(point); 
				}else if(point.steps<top.steps){
					top.steps-=point.steps;
					s.pop();
					s.push(top);
				}
			}
			else{//如果当前动作与栈顶动作不相反,则直接将当前动作压入栈中 
				s.push(point) ;
			} 
		} 
	}
	vector<Action> result;//用来存储结果的向量
	while(!s.empty()){//逆序进行处理栈中的元素,并合并同一方向的步数 ,遍历 
		Action point=s.top();//获取栈顶元素(结构体) 
		s.pop();//弹出栈顶元素(结构体)
		//方向倒置一下进行输出 
		if(point.direction==1){
			point.direction=2;
		} else if(point.direction==2){
			point.direction=1;
		}else if(point.direction==3){
			point.direction=4;
		}else if(point.direction==4){
			point.direction=3;
		}
		if(!result.empty()&& point.direction==result.back().direction){//如果当前动作和结果中最后一个动作一致 
			result.back().steps+=point.steps;//result.back()是对最后一个元素的引用,相当于最新加入的元素 
		}else{
			result.push_back(point);//如果不同,证明方向已经改变或者是第一个元素,加入该元素。 
		} 
	}
	return result; //结构体向量 
} 
vector<Action> x;//存储每一步的全部信息 
int main(){
	int x1,y1;
	char xing;
	while(panduan){//读取方向,节点元素 
	 Action po; 
	 cin>>x1>>xing>>y1;
	 po.direction=x1;
	 po.steps=y1;
	 x.push_back(po);
	 if(x1==0&&y1==0){
	 	panduan=false;
	 }
	}
	vector<Action> y=shortest(x);//再创建一个结构体向量接收返回结果 
	for(int i=0;i<y.size();i++){
		Action action=y[i];
		if(action.direction==0&&action.steps==0){
			continue;
		}else{
			cout<<action.direction<<"-"<<action.steps<<endl;
		}
	}
} 

欢迎指正。

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值