洛谷网 1126机器人搬重物 优先队列搜索 一般

点击打开题目

题目描述

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

输入输出格式

输入格式:

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

输出格式:

一个整数,表示机器人完成任务所需的最少时间。如果无法到达,输出-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





















题目不难,但是要注意如果遇到障碍物或者遇到边缘部分,就不能继续走,其他的就用优先队列解决。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<map>
using namespace std;
struct node
{
	int x,y,time,to;//to的值为1,2,3,4分别代表北,东,南,西方向 
	bool friend operator<(node c,node d)
	{
		return c.time>d.time;
	} 
}no,ne;
int g[60][60],G[60][60];
int vis_dir[60][60][5];//标记地图上的点是否已用同样的方向走过 
int mark[60][60];//标记目的地 
int N,M;
map<char,int>dir;
priority_queue<node>q;
char s;
void init()
{
	memset(g,0,sizeof(g));
	memset(G,0,sizeof(G));
	memset(vis_dir,0,sizeof(vis_dir));
	memset(mark,0,sizeof(mark));
	dir['N']=1;
	dir['E']=2;
	dir['S']=3;
	dir['W']=4;
}
void transfer()//转换地图 
{	
	for(int i=1;i<=N;i++)
	for(int j=1;j<=M;j++)
	if(g[i][j]==1)
	G[i][j]=G[i-1][j]=G[i][j-1]=G[i-1][j-1]=1;
}
void bfs()
{
	int i,j,k;
	while(!q.empty())
	{
		no=q.top();
		q.pop();
		if(mark[no.x][no.y]==-1)
		{
			printf("%d\n",no.time);
			return;
		}
		vis_dir[no.x][no.y][no.to]=1;
		if(no.to%2==1)//如果方向为北或者南,移动x 
		{
			k=no.to-2;//to=1为北,x往北边移,to=3同理 
			for(i=k;i!=4*k;i+=k)
			{
				ne.y=no.y;
				ne.x=no.x+i;
				ne.time=no.time+1;
				ne.to=no.to;
				if(ne.x>=0&&ne.x<=N&&!vis_dir[ne.x][ne.y][ne.to])
				{
					if(G[ne.x][ne.y]==1||ne.x==0||ne.x==N)//移动的过程遇到障碍物或者不能移动,终止循环 
					break;
					q.push(ne);
					vis_dir[ne.x][ne.y][ne.to]=1;
				}
			}
		}
		else//同上 
		{
			k=3-no.to;
			for(i=k;i!=4*k;i+=k)
			{
				ne.x=no.x;
				ne.y=no.y+i;
				ne.time=no.time+1;
				ne.to=no.to;
				if(ne.y>=0&&ne.y<=M&&!vis_dir[ne.x][ne.y][ne.to])
				{
					if(G[ne.x][ne.y]==1||ne.y==0||ne.y==M)
					break;
					q.push(ne);
					vis_dir[ne.x][ne.y][ne.to]=1; 
				}
			}
		}
		for(i=no.to+1;i<=no.to+3;i+=2)//左右换方向 
		{
			ne.x=no.x;
			ne.y=no.y;
			ne.time=no.time+1;
			ne.to=i;
			while(ne.to>4)
			ne.to-=4;
			if(!vis_dir[ne.x][ne.y][ne.to])
			{
				q.push(ne);
				vis_dir[ne.x][ne.y][ne.to]=1;
			}
		}
	}
	printf("-1\n");
	return;
}
int main()
{
	int i,j;
	scanf("%d%d",&N,&M);
	init();
	for(i=1;i<=N;i++)
	for(j=1;j<=M;j++)
	scanf("%d",&g[i][j]);
	transfer();
	cin>>no.x>>no.y>>i>>j>>s;
	no.time=0;
	no.to=dir[s];
	mark[i][j]=-1;
	q.push(no);
	bfs();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙橘子猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值