列表

详情


NC230361. 拯救美少女

描述

美少女之神被邪恶的马也怪偷袭并被囚禁在了地牢中!你身为美少女教第一勇士,救出美少女之神义不容辞!

美少女教教主已为你绘制好了地牢的地图,地图由nm字符组成。'.'表示地面,'#'表示墙壁,'A'表示马也怪(有且仅有一个),'S'表示地牢入口,'T'表示美少女之神所在位置。

小心!马也怪每隔单位时间会在自身位置释放一个魔球(消耗1单位时间),魔球每单位时间会朝远离(即魔球至马也怪的曼哈顿距离增加)马也怪的方向扩散(扩散后原魔球消失,具体形式见提示2),被魔球击中的生物将变成邪恶触手怪。你和魔球都无法通过墙壁。

现在距离美少女之神被抓已经过了个单位时间(即保证马也怪第一次释放的魔球在无墙壁阻拦的情况下已全部扩散出边界),你可以在之后的任意时刻进入地牢(不耗时),请判断是否有可能在不碰到魔球与马也怪的情况下救出美少女之神。

保证美少女之神所在坐标魔球无法到达,所有移动均为上下左右,你和魔球同时移动且移速为每单位时间一格,到达T位置视为成功拯救

输入描述

第一行输入正整数
第二行输入正整数
之后n行输入地牢地图。

输出描述

若能救出美少女之神,输出"YES" ,否则输出"NO"。

示例1

输入:

5 5
3
.T#..
.#...
....A
..S..
.....

输出:

YES

示例2

输入:

5 5
1
.T#..
.#...
....A
..S..
.....

输出:

NO

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 176ms, 内存消耗: 6264K, 提交时间: 2021-11-11 14:53:55

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstring>
#include <string>
#include <map>
#include <set>
#include <iostream>
#include <ctime>

using namespace std;

const int N = 1024;

struct node{
	int x,y,life;
	node(){}
	node(int x,int y,int life = 0) :
		x(x),y(y),life(life) {}
}s,t,boss;

int n,m,k;
char cmap[N][N];

int dx[4] = {1,-1,0,0}; //上下左右
int dy[4] = {0,0,-1,1};
int maxLife[N][N];
bool safe[N][N];

void getSafeArea();
/*
通过观察可以发现
存在一些固定区域魔球无法到达(安全区域)
所以先模拟魔球的扩散处理出这些区域
*/
bool isReachable();
/*
当勇者不在安全区域中时
相邻的两圈魔球到马也怪(圆心)的半径之差为k + 1(即有k格没有魔球)
若勇者朝着靠近马也怪方向移动,则勇者与魔球相向而行
勇者最多可以走 (k - 1) / 2 回合
若勇者朝着远离马也怪方向移动,则勇者与魔球同向而行
勇者可以走无限多回合
*/

inline bool isLegal(int px,int py){
	if(px < 0 || py < 0 || px >= n || py >= m) return false;
	if(cmap[px][py] == 'A' || cmap[px][py] == '#') return false;
	return true;
}

int main(){

	/*freopen("8.in","r",stdin);
	clock_t st,ed;
	st = clock();*/

	scanf("%d %d %d",&n,&m,&k);
	for(int i = 0;i < n;i++){
		scanf("%s",cmap[i]);
		for(int j = 0;j < m;j++){
			if(cmap[i][j] == 'S') s = node(i,j);
			else if(cmap[i][j] == 'T') t = node(i,j);
			else if(cmap[i][j] == 'A') boss = node(i,j);
		}
	}
	getSafeArea();
	printf("%s\n",isReachable() ? "YES" : "NO");

	/*ed = clock();
	printf("%lf\n",(double)(ed - st) / CLOCKS_PER_SEC);
	fclose(stdin);*/
	
	return 0;
}

void getSafeArea(){
	queue <node> q;
	q.push(boss);
	while(!q.empty()){
		node cur = q.front();
		q.pop();
		safe[cur.x][cur.y] = true;

		int px,py;
		if(cur.x >= boss.x){
			px = cur.x + dx[0];
			py = cur.y + dy[0];
			if(isLegal(px,py) && !safe[px][py]){
				safe[px][py] = true;
				q.push(node(px,py));
			}
		}
		if(cur.x <= boss.x){
			px = cur.x + dx[1];
			py = cur.y + dy[1];
			if(isLegal(px,py) && !safe[px][py]){
				safe[px][py] = true;
				q.push(node(px,py));
			}
		}
		if(cur.y <= boss.y){
			px = cur.x + dx[2];
			py = cur.y + dy[2];
			if(isLegal(px,py) && !safe[px][py]){
				safe[px][py] = true;
				q.push(node(px,py));
			}
		}
		if(cur.y >= boss.y){
			px = cur.x + dx[3];
			py = cur.y + dy[3];
			if(isLegal(px,py) && !safe[px][py]){
				safe[px][py] = true;
				q.push(node(px,py));
			}
		}
	}
}
bool isReachable(){
	//memset(maxLife,-1,sizeof(maxLife));
	maxLife[s.x][s.y] = k;
	queue <node> q;
	q.push(node(s.x,s.y,k));
	while(!q.empty()){
		node cur = q.front();
		q.pop();

		if(cur.x == t.x && cur.y == t.y) return true;

		for(int i = 0;i < 4;i++){
			int px = cur.x + dx[i];
			int py = cur.y + dy[i];
			int life = cur.life;

			if(!isLegal(px,py)) continue;
			if(abs(px - boss.x) + abs(py - boss.y) < abs(cur.x - boss.x) + abs(cur.y - boss.y)) life -= 2;
			if(!safe[px][py]) life = k;
			if(life <= 0 || life <= maxLife[px][py]) continue;
			
			maxLife[px][py] = life;
			q.push(node(px,py,life));
		}
	}
	return false;
}

上一题