欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

洛谷P1126 机器人搬重物

程序员文章站 2022-06-12 09:38:01
...

题目描述

机器人移动学会(RMI)现在正尝试用机器人搬运物品。机器人的形状是一个直径 $1.6 米的球。在试验阶段,机器人被用于在一个储藏室中搬运货物。储藏室是一个 N×M 的网格,有些格子为不可移动的障碍。机器人的中心总是在格点上,当然,机器人必须在最短的时间内把物品搬运到指定的地方。机器人接受的指令有:向前移动 1 步(Creep);向前移动2步(Walk);向前移动 3 步(Run);向左转(Left);向右转(Right)。每个指令所需要的时间为 1 秒。请你计算一下机器人完成任务所需的最少时间。

输入输出格式

输入格式:

 

第一行为两个正整数 N,M(N,M≤50),下面 N 行是储藏室的构造, 0 表示无障碍, 1 表示有障碍,数字之间用一个空格隔开。接着一行有 4个整数和 1 个大写字母,分别为起始点和目标点左上角网格的行与列,起始时的面对方向(东 E ,南 S ,西 W ,北 N ),数与数,数与字母之间均用一个空格隔开。终点的面向方向是任意的。

 

输出格式:

 

一个整数,表示机器人完成任务所需的最少时间。如果无法到达,输出 −−1 。

洛谷P1126 机器人搬重物

输入输出样例

输入样例#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

思路

这道题可以说是非常阴险了,本来只是一道很简单的广搜,结果被阴险的出题人硬生生地挖了好多坑,难度直接升到提高QAQ。

第一个坑:要将格子图转换为点图。

第二个坑:机器人是有半径的,所以要处理边界,而且障碍物周围的四个点都不能走。

第三个坑:方向非常麻烦,必须处理好。

只要解决了这几个坑 ,剩下的广搜就非常简单了,在这里不解释。

广搜模板:https://blog.csdn.net/zhuyifan_jizhi/article/details/81112014

代码

// 先看主函数是一种好习惯
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
bool map[51][51];
int vis[51][51][5];//行、列、方向 
int dx[4]= {0,1,0,-1},dy[4]= {1,0,-1,0};
struct node {
	int x,y,dir,step;//分别为行,列,方向,步数
};
queue<node> q;
node aaa;
int tx,ty,f,st,x1,x2,y1,y2,n,m;
int ans[5001]= {-1},tot,minl=0x7fffff;
int fx[5]= {0,1,0,-1},
           fy[5]= {1,0,-1,0};
void bfs() {
	while(!q.empty()) {
		aaa=q.front();
		q.pop();
		tx=aaa.x;
		ty=aaa.y;
		if(tx==x2 && ty==y2) {//满足条件,直接输出 
			printf("%d",aaa.step) ;
			return;
		}
		for(int j=1; j<=3; j++) {//1~3步 
			tx+=fx[aaa.dir];
			ty+=fy[aaa.dir] ;
			if( tx <= 0 || ty <= 0 || tx >= n || ty >= m || map[tx][ty]==1 )//如果到边界或遇到障碍,结束循环 
				break ;
			else if(!vis[tx][ty][aaa.dir]) {
				vis[tx][ty][aaa.dir]=true;
				node cnew;
				cnew.x=tx;
				cnew.y=ty;
				cnew.dir=aaa.dir;
				cnew.step=aaa.step+1;
				q.push(cnew);
			}
		}
		//还是处理方向(这里有些难理解) 
		//当碰到障碍,就会break到这里转向 
		node cnew;
		cnew.x=aaa.x;
		cnew.y=aaa.y;
		cnew.step=aaa.step+1;
		cnew.dir=aaa.dir-1;
		if(cnew.dir==-1)cnew.dir=3;//从东向西转,转到北 
		if(!vis[cnew.x][cnew.y][cnew.dir]) {
			vis[cnew.x][cnew.y][cnew.dir]=true;
			q.push(cnew);
		}
		cnew.dir=aaa.dir+1;
		if(cnew.dir==4)cnew.dir=0;//从北向东转,转到东 
		if(!vis[cnew.x][cnew.y][cnew.dir]) {
			vis[cnew.x][cnew.y][cnew.dir]=true;
			q.push(cnew);
		}
	}
	cout<<-1;
}
int main() {
	cin>>n>>m;
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=m; j++) {
			bool a;
			cin>>a;
			//处理障碍
			if(a) {
				map[i][j]=1;
				map[i-1][j-1]=1;
				map[i-1][j]=1;
				map[i][j-1]=1;
			}
		}
	}
	//处理边界 
	for(int i=1; i<=n; i++) {
		map[n][i]=1;
		map[i][m]=1;
	}
	char fang;
	cin>>x1>>y1>>x2>>y2>>fang;
	//处理方向 
	if(fang=='E') aaa.dir=0;
	else if(fang=='S') aaa.dir=1;
	else if(fang=='W') aaa.dir=2;
	else aaa.dir=3;
	aaa.x=x1;
	aaa.y=y1;
	aaa.step=0;
	q.push(aaa);
	bfs();
	return 0;
}