机器人搬重物
题目描述
机器人移动学会(RMI)现在正尝试用机器人搬运物品。机器人的形状是一个直径 1.6 1.6 1.6 米的球。在试验阶段,机器人被用于在一个储藏室中搬运货物。储藏室是一个 N × M N\times M N×M 的网格,有些格子为不可移动的障碍。机器人的中心总是在格点上,当然,机器人必须在最短的时间内把物品搬运到指定的地方。机器人接受的指令有:
- 向前移动
1
1
1 步(
Creep
); - 向前移动
2
2
2 步(
Walk
); - 向前移动
3
3
3 步(
Run
); - 向左转(
Left
); - 向右转(
Right
)。
每个指令所需要的时间为 1 1 1 秒。请你计算一下机器人完成任务所需的最少时间。
输入格式
第一行为两个正整数 N , M ( 1 ≤ N , M ≤ 50 ) N,M\ (1\le N,M\le50) N,M (1≤N,M≤50),下面 N N N 行是储藏室的构造, 0 0 0 表示无障碍, 1 1 1 表示有障碍,数字之间用一个空格隔开。接着一行有 4 4 4 个整数和 1 1 1 个大写字母,分别为起始点和目标点左上角网格的行与列,起始时的面对方向(东 E \tt E E,南 S \tt S S,西 W \tt W W,北 N \tt N N),数与数,数与字母之间均用一个空格隔开。终点的面向方向是任意的。
输出格式
一个整数,表示机器人完成任务所需的最少时间。如果无法到达,输出 − 1 -1 −1。
样例 #1
样例输入 #1
9 10
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 1 0
7 2 2 7 S
样例输出 #1
12
思路+细节
本道题我们我们看数据范围,不怎么大,因此我们用dfs(其实后面觉得bfs更好更优,但是我懒,不想写bfs),但单纯的dfs,可能会爆栈,因此我们想到记忆化搜索,我们用,f[i][j][k]
来表示在坐标某点且此时微米某个方向的步数集合,如果当我们的步数比这个记忆化的来的大,我们就不用继续搜索了。为什么呢?因为你都比他大了,那后边搜索的就不是最优的了,就没有搜索的必要了。特别注意,如果是记忆化搜索,那就不需要st数组了。
本道题有很多细节。
- 细节1:机器人有体积,因此不能在x=0或者n,y=m或者0上。
- 细节2:图中已经给了我们方向了(x向下,向右),因此这个地方要写对应,就比如方向为N,此时是y不变,x变化(这个地方搞错卡了好久)。
- 细节3:题目给定3种速度,分别为1,2,3,特别注意就是,你可以走3,2,步的前提就是在这3,2步的直线上(也就是走过的直线)不能有黑点。
- 细节4:题目测试用例给的图是框框图,而不是点图。因此题目给的0应该它的四周都是1(很明显,你自己对应一下题目给你的图),这点很重要,空格图转化为点图。
代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 60;
int w[N][N];
bool st[N][N];
int n,m;
int stx,sty,edx,edy;
char op1;
int ans=0x3f3f3f3f;
int f[N][N][5];//已经搜到的步数
//记忆化应该适用于有明确每个阶段采用
char op[]={'N','E','S','W'};
int change(char s){
if(s=='N'){
return 0;
}else if(s=='E'){
return 1;
}else if(s=='S'){
return 2;
}else{
return 3;
}
}
void dfs(int x,int y,int step,char s){
if(x==edx&&y==edy){
ans=min(ans,step);
return;
}
if(step>=f[x][y][change(s)])return;
f[x][y][change(s)]=step;
//五个方式轮流
dfs(x,y,step+1,op[((change(s)-1)%4+4)%4]);//左转
dfs(x,y,step+1,op[((change(s)+1)%4+4)%4]);
if(s=='N'){
if(x-3>0&&w[x-3][y]==0&&w[x-2][y]==0&&w[x-1][y]==0)dfs(x-3,y,step+1,s);
if(x-2>0&&w[x-2][y]==0&&w[x-1][y]==0)dfs(x-2,y,step+1,s);
if(x-1>0&&w[x-1][y]==0)dfs(x-1,y,step+1,s);
}else if(s=='E'){
if(y+3<m&&w[x][y+1]==0&&w[x][y+2]==0&&w[x][y+3]==0)dfs(x,y+3,step+1,s);
if(y+2<m&&w[x][y+2]==0&&w[x][y+1]==0)dfs(x,y+2,step+1,s);
if(y+1<m&&w[x][y+1]==0)dfs(x,y+1,step+1,s);
}else if(s=='S'){
if(x+3<n&&w[x+1][y]==0&&w[x+2][y]==0&&w[x+3][y]==0)dfs(x+3,y,step+1,s);
if(x+2<n&&w[x+1][y]==0&&w[x+2][y]==0)dfs(x+2,y,step+1,s);
if(x+1<n&&w[x+1][y]==0)dfs(x+1,y,step+1,s);
}else{
if(y-3>0&&w[x][y-1]==0&&w[x][y-2]==0&&w[x][y-3]==0)dfs(x,y-3,step+1,s);
if(y-2>0&&w[x][y-1]==0&&w[x][y-2]==0)dfs(x,y-2,step+1,s);
if(y-1>0&&w[x][y-1]==0) dfs(x,y-1,step+1,s);
}
}
int main(){
cin>>n>>m;
memset(f,0x3f,sizeof f);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int x;
cin>>x;
if(x==1){
w[i][j]=w[i-1][j-1]=w[i-1][j]=w[i][j-1]=1;
}
}
}
cin>>stx>>sty>>edx>>edy>>op1;
dfs(stx,sty,0,op1);
if(ans==0x3f3f3f3f)ans=-1;
cout<<ans;
return 0;
}