【问题描述】老鼠找食物,但是回家的时候找到最短路径,输入是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;
}
}
}
欢迎指正。