GDUT_寒假训练题解报告_专题I_G题 个人题解报告

GDUT_寒假训练题解报告_专题I_G题 个人题解报告

题目:

你要玩一个新的角色扮演。图中的世界地图由n × m个单元格组成的网格表示。任何在某个单元格中的角色都可以从该单元格向四个方向移动-向左、向右、向前和向后移动单元格,但不能离开世界地图。

怪物生活在一些牢房里。如果在某个时刻,你在一个可以被一个d步或更小步数的怪物接近的牢房里,他会立刻跑过去杀死你。

你必须从游戏场的一个单元活到另一个单元。确定是否可行,如果可行,则找到执行此操作所需的最少步骤数。

输入

第1行包含三个非负整数n、m和d(0<=n*m<=200000,0<=d<=200000)——图的大小和怪物危险的最大距离。

接下来的n行中的每行包含m个字符。这些字符可以等于’S’,’.’,‘M’,‘F’ '开始”和“完成”单元格为空,并且只在输入中显示一次。

输出

如果可以从起始单元到结束单元激活,则输出执行此操作所需的最少步骤数。否则,输出“-1”。

样例:
input

5 7 1
S.M…M


M…M…
…F

Output

12

Input

7 6 2
S…
…M…

…M

M…
…F

Output

11

Input

7 6 2
S…
…M…


…M
M…
…F

Output

-1

Input

4 4 2
M…
.S…

…F

Output

-1
这个题目首先是bfs走迷宫得到最短路径,但是存在两个问题:

1.数据范围,数据给出n*m<=2e5,也就是说有可能n为1,m为2e5,那么开一个[2e5][2e5]的数组肯定不行,会爆的,所以要动态分配内存,或者用一维数组存二维数组的信息,

2.M这个影响,如果一个点同时被多个M影响,就会出现重复赋值问题,这样复杂度就上去了,可以开一个复刻数组来记录是否已经被更近的M影响,但是减少得最多的还是使用队列:把影响都放到队列里面,用bfs的手段来进行Monster的影响覆盖,这样的话就能有效剪枝,如果所有影响的面积是n,能比第一种方法少n步。





具体做法:动态数组好办,关键是如何搞定M的影响,

第一步,所有的M都放到队列里面,这里我以结构体的形式存坐标信息

typedef struct coordinate
{int x_;int y_;}coor;

放到队列里面的做法是这样的,令monster的值为d+1,其余值为0然后开始他的扩散:

else if(ch=='M')
			{
				all[time][time1]=d+1;
				coor co_;
				co_.x_=time;
				co_.y_=time1;
				que.push(co_);
			}

现在可以开始了,把所有的monster放到队列里面,然后开始每次都影响周围四个比自己小2的格子,因为如果自己是k,下一个已经是k-1,说明前面已经有monster对其进行影响了,这时候就要跳过,不能多此一举,同理如果是更大的,说明有更近的monster已经对其施加了影响,这时候也要跳过。

while(!que.empty())
	{
		coor co=que.front();
		if((co.x_+1<n)&&all[co.x_+1][co.y_]<all[co.x_][co.y_]-1)
		{
			all[co.x_+1][co.y_]=all[co.x_][co.y_]-1;
			co.x_++;
			que.push(co);
			co.x_--;
		}
		if((co.x_-1>=0)&&all[co.x_-1][co.y_]<all[co.x_][co.y_]-1)
		{
			all[co.x_-1][co.y_]=all[co.x_][co.y_]-1;
			co.x_--;
			que.push(co);
			co.x_++;
		}
		if((co.y_+1<m)&&all[co.x_][co.y_+1]<all[co.x_][co.y_]-1)
		{
			all[co.x_][co.y_+1]=all[co.x_][co.y_]-1;
			co.y_++;
			que.push(co);
			co.y_--;
		}
		if((co.y_-1>=0)&&all[co.x_][co.y_-1]<all[co.x_][co.y_]-1)
		{
			all[co.x_][co.y_-1]=all[co.x_][co.y_]-1;
			co.y_--;
			que.push(co);
			co.y_++;
		}
		que.pop();
	}

做完这一步,剩下就是一个普通的bfs求二维空间最短路径了,但是我的做法是让受影响的点为1——d+1,不受影响的点为0,怎么来表示路径长度呢,我用了负数,用负数表示起点到此的最短路径。
那么:完整代码如下:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <queue>

#define ULL unsigned long long
using namespace std;

typedef struct coordinate
{int x_;int y_;}coor;
queue<coor>que;
int n,m,d;
int start_x,start_y,end_x,end_y;

int main()
{
	scanf("%d %d %d",&n,&m,&d);
	int all[n+1][m+1];
	memset(all,0,sizeof(all));
	getchar();
	for(int time=0;time<n;time++)
	{
		for(int time1=0;time1<m;time1++)
		{
			char ch;
			ch=getchar();
			if(ch=='S'){all[time][time1]=0;start_x=time;start_y=time1;}
			else if(ch=='F'){all[time][time1]=0;end_x=time;end_y=time1;}
			else if(ch=='.'){all[time][time1]=0;}
			else if(ch=='M')
			{
				all[time][time1]=d+1;
				coor co_;
				co_.x_=time;
				co_.y_=time1;
				que.push(co_);
			}
		}
		getchar();
	}
	//input finished;
	while(!que.empty())
	{
		coor co=que.front();
		if((co.x_+1<n)&&all[co.x_+1][co.y_]<all[co.x_][co.y_]-1)
		{
			all[co.x_+1][co.y_]=all[co.x_][co.y_]-1;
			co.x_++;
			que.push(co);
			co.x_--;
		}
		if((co.x_-1>=0)&&all[co.x_-1][co.y_]<all[co.x_][co.y_]-1)
		{
			all[co.x_-1][co.y_]=all[co.x_][co.y_]-1;
			co.x_--;
			que.push(co);
			co.x_++;
		}
		if((co.y_+1<m)&&all[co.x_][co.y_+1]<all[co.x_][co.y_]-1)
		{
			all[co.x_][co.y_+1]=all[co.x_][co.y_]-1;
			co.y_++;
			que.push(co);
			co.y_--;
		}
		if((co.y_-1>=0)&&all[co.x_][co.y_-1]<all[co.x_][co.y_]-1)
		{
			all[co.x_][co.y_-1]=all[co.x_][co.y_]-1;
			co.y_--;
			que.push(co);
			co.y_++;
		}
		que.pop();
	}
	//完成赋值,接下来该走普普通通板子bfs了
	if(all[start_x][start_y]!=0){printf("-1\n");}
	else
	{
		queue<coor>bfs_;
		coor start;
		start.x_=start_x;
		start.y_=start_y;
		bfs_.push(start);
		all[start_x][start_y]=-1;
		while(!bfs_.empty())
		{
			coor next=bfs_.front();
			bfs_.pop();

			if((next.x_+1<n)&& all[next.x_+1][next.y_]==0 )
			{
				all[next.x_+1][next.y_]=all[next.x_][next.y_]-1;
				next.x_++;
				bfs_.push(next);
				next.x_--;
			}
			if((next.x_-1>=0)&& all[next.x_-1][next.y_]==0 )
			{
				all[next.x_-1][next.y_]=all[next.x_][next.y_]-1;
				next.x_--;
				bfs_.push(next);
				next.x_++;
			}
			if((next.y_+1<m)&& all[next.x_][next.y_+1]==0 )
			{
				all[next.x_][next.y_+1]=all[next.x_][next.y_]-1;
				next.y_++;
				bfs_.push(next);
				next.y_--;
			}
			if((next.y_-1>=0)&& all[next.x_][next.y_-1]==0 )
			{
				all[next.x_][next.y_-1]=all[next.x_][next.y_]-1;
				next.y_--;
				bfs_.push(next);
				next.y_++;
			}
		}
		if(all[end_x][end_y]>=0)printf("-1");
		else printf("%d\n",-1-all[end_x][end_y]);
	}


    return 0;
}
发布了8 篇原创文章 · 获赞 0 · 访问量 115

猜你喜欢

转载自blog.csdn.net/DevourPower/article/details/103962920