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;
}