• 机器人搬重物


    题目:

    Description

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

    Input

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

    Output

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


    思路:

    • map:记录是否能走
    • flag:记录当前状态是否出现
    • dir:记录向四个方向走横纵坐标的变化
    • a:当前坐标向左向右转分别代表的数字
    • 0——N,1——W,2——S,3——E
      现将格图转换为点图(自己画图模拟),输入的障碍坐标应为点图的左上角,此时要将余下3个点标为假,起点和终点的坐标都要+1
     void change(int i,int j)
    {
    	map[i][j]=false; 
    	map[i+1][j]=map[i][j+1]=map[i+1][j+1]=false;
    }
     void init()
    {
    	memset(map,1,sizeof(map));
    	scanf("%d%d",&n,&m);
    	int a;
    	char b;
    	for (int i=1; i<=n; i++)
    		for (int j=1; j<=m; j++)
    		{
    			scanf("%d",&a);
    			if (a) change(i,j); 
    		}
    	cin>>sx>>sy>>ex>>ey>>b;
    	sx++; sy++; ex++; ey++;
    	if (b=='N') f[1].d=0;
    	else if (b=='W') f[1].d=1;
    	else if (b=='S') f[1].d=2;
    	else f[1].d=3;//判断机器人起点时的面向方向
    }
    
     BFS中判断是否到达终点,到达立即输出。先改变机器人的面向方向,加入队列;再枚举走的步数。
    
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    const int N=55;
     struct ss
    {
    	int x,y,d,ans;
    }f[N*N*5];
    bool map[N][N],flag[N][N][N];
    int n,m,sx,sy,ex,ey;
    int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
    int a[3][4]={{0,1,2,3},{1,2,3,0},{3,0,1,2}};
    
     void change(int i,int j)
    {
    	map[i][j]=false; 
    	map[i+1][j]=map[i][j+1]=map[i+1][j+1]=false;
    }
     void init()
    {
    	memset(map,1,sizeof(map));
    	scanf("%d%d",&n,&m);
    	int a;
    	char b;
    	for (int i=1; i<=n; i++)
    		for (int j=1; j<=m; j++)
    		{
    			scanf("%d",&a);
    			if (a) change(i,j); 
    		}
    	cin>>sx>>sy>>ex>>ey>>b;
    	sx++; sy++; ex++; ey++;
    	if (b=='N') f[1].d=0;
    	else if (b=='W') f[1].d=1;
    	else if (b=='S') f[1].d=2;
    	else f[1].d=3;
    }
     bool pd(int i,int j)
    {
    	if (i<=1||i>n||j<=1||j>m) return false;
    	return true;
    }
     void bfs()
    {
    	int l=0,r=1;
    	f[1].x=sx; f[1].y=sy; f[1].ans=0;
    	while (l<r)
    	{
    		l++;
    		if (f[l].x==ex&&f[l].y==ey)
    		{
    			printf("%d\n",f[l].ans); return;
    		}
    		int xx,yy,di;
    		for (int i=1; i<=2; i++) 
    		{
    			di=a[i][f[l].d];
    			if (!flag[f[l].x][f[l].y][di])
    			{
    				flag[f[l].x][f[l].y][di]=true;
    				r++;
    				f[r].x=f[l].x; f[r].y=f[l].y; f[r].ans=f[l].ans+1; f[r].d=di;
    			}
    		}
    		for (int i=1; i<=3; i++)
    		{
    			xx=f[l].x+i*dir[f[l].d][0];
    			yy=f[l].y+i*dir[f[l].d][1];
    			if (map[xx][yy]&&pd(xx,yy))
    			{
    				if (!flag[xx][yy][f[l].d])
    				{
    					flag[xx][yy][f[l].d]=true;
    					r++; 
    					f[r].x=xx; f[r].y=yy; f[r].ans=f[l].ans+1; f[r].d=f[l].d;
    				}
    			}
    			else break;
    		}
    	}
    	printf("-1\n");
    }
     int main()
    {
    	init();
    	bfs();
    	return 0;
    }
    
  • 相关阅读:
    灰哥的二叉树
    BZOJ1029: [JSOI2007]建筑抢修[模拟 贪心 优先队列]
    POJ1155TELE[树形背包]
    HDU4003Find Metal Mineral[树形DP 分组背包]
    POJ1837 Balance[分组背包]
    HDU2639Bone Collector II[01背包第k优值]
    POJ3666Making the Grade[DP 离散化 LIS相关]
    HDU2955 Robberies[01背包]
    HDU2191悼念512汶川大地震遇难同胞——珍惜现在,感恩生活[多重背包]
    POJ1014Dividing[多重背包可行性]
  • 原文地址:https://www.cnblogs.com/lyxzhz/p/11405024.html
Copyright © 2020-2023  润新知