3268. 神奇怪兽在哪里
Time limit per test: 2.0 seconds
Memory limit: 256 megabytes
熊猫先生最近在玩一款单机游戏。
在游戏中,会有一张 n 行 m 列的地图(如样例中所示)。用 .
表示空地,用 *
表示怪兽,用 P
表示熊猫先生现在所在的位置。怪兽只有一个,所以由 *
组成的块一定是一个上下左右四连通块。游戏的规则是:熊猫先生要把怪兽「包住」,并且回到现在所在的位置,才能把怪兽消灭掉。
「包住」的含义是:走过的路径可以将怪兽封闭起来。只能在空地上行走。走过的路径可以相交,可以重叠,可以重复走,只要围住就好了。
由于这是一款在命令行下运行的复古单机游戏,熊猫先生只能按上下左右四个键,即他只能向上下左右四个方向移动。你能找到一种消灭怪兽的方法吗?
Input
输入包含多个测试文件,每个测试文件是单组测试数据。
第一行两个整数 n,m (1≤n,m≤100)。对于 30% 的数据,满足:1≤n,m≤20。
接下来 n 行,每行一个长度为 m 的字符串,表示地图。
.
表示空地,*
表示怪兽,P
表示熊猫先生现在所在的位置。输入保证熊猫先生不会出现在「怪兽里面」。
Output
输出一行,一个字符串,表示要消灭怪兽所要执行的操作序列:
- 向上走用
U
表示; - 向下走用
D
表示; - 向左走用
L
表示; - 向右走用
R
表示。
输入保证有解。输出任意一解即可。
Examples
6 10 .......... ...***..P. ..**...... ..*****... .....***.. ..........
DDDDLLLLLLULUUUURRRRRRDR
Note
样例给出的答案路径是:
.PPPPPPP.. .P.***.PP. .P**....P. .P*****.P. .PP..***P. ..PPPPPPP.
答案可以有多种情形,围出下面的形式也是可以的:
.PPPPPPP.. .P.***.PP. .P**PPPPP. .P*****.P. .PP..***P. ..PPPPPPP.
注意在这种方案中,走过的路发生了重叠。
你甚至还可以绕多圈,以至于变成了这样:
PPPPPPPPPP PPP***PPPP PP**PPPPPP PP*****PPP PPPPP***PP PPPPPPPPPP
只要你的输出序列能让你回到原点,这种情况也是正确的。
中文题意不解释。
一开始看到这道题觉得常规搜索题,毕竟最近这一周一直在肝搜索。
但是一开始还是无从下手,不知道怎么搜。
后来想了一下,只需从起点出发,搜到任意的一个角落(把这个路径记录下来,然后绕一圈再回到原处就可以了。
所以是dfs,但这里一开始犯了一个错误。
就是dfs并不是一定搜的就是正确的。所以在回溯的时候需要删除末尾元素(vector真是好用。
绕过了这几个坑就没什么问题了。
dfs是要比bfs难一点啊...
//#include <bits/stdc++.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <queue>
#include <stack>
#include <algorithm>
#define __max(a,b) (((a) > (b)) ? (a) : (b))
#define __min(a,b) (((a) < (b)) ? (a) : (b))
using namespace std;
const int maxn = 500;
const int N = 2e3+10;
bool used[N][maxn];
bool Prime[maxn];
char maze[maxn][maxn];
typedef pair<int,int> P;
int dx[] = {-1,0,0,1,0,0};
int dy[] = {0,-1,1,0,0,0};
int dz[] = {0,0,0,0,-1,1};
typedef long long ll;
int t,n,m;//t记录到达四个角所需要的步数
int flag;
const char dire[5] = "ULRD";//映射方向
vector<int> ans;
void solve(int mode)//填充绕一圈的路径
{
switch (mode) {
case 0:
for(int i = 0; i < n-1; i++)
ans.push_back(0);
break;
case 1:
for(int i = 0; i < m-1; i++)
ans.push_back(1);
break;
case 2:
for(int i = 0; i < m-1; i++)
ans.push_back(2);
break;
case 3:
for(int i = 0; i < n-1; i++)
ans.push_back(3);
break;
default:
break;
}
}
void dfs(int x, int y){
if(flag) return;
used[x][y] = 1;
if(x == 0 && y == 0){
solve(3);solve(2);solve(0);solve(1);
flag = 1;return;
}
if(x == 0 && y == m-1){
solve(3);solve(1);solve(0);solve(2);
flag = 1;return;
}
if(x == n-1 && y == 0){
solve(0);solve(2);solve(3);solve(1);
flag = 1;return;
}
if(x == n-1 && y == m-1){
solve(1);solve(0);solve(2);solve(3);
flag = 1;return;
}
for(int i = 0; i < 4; i++)
{
int px = dx[i] + x, py = dy[i] +y;
if(maze[px][py] != '*' && px >= 0 && px < n && py >=0 && py < m && used[px][py] == 0)
{
t++;//到达四个角所需步数
ans.push_back(i);
used[px][py] = 1;
dfs(px, py);
if(flag) return;
ans.pop_back();//回溯时如果不是搜到了就要删除末尾元素
t--;//路径数量要减去1
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
//freopen("/Users/vector/Desktop/input.txt", "r", stdin);
cin>>n>>m;
{
memset(used,0,sizeof(used));
for(int i = 0; i < n; i++)
cin>>maze[i];
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
{
if(maze[i][j] == 'P')
{dfs(i,j);break;}
}
for(int i = t-1; i >= 0; i--)
ans.push_back(3-ans[i]);//反方向的路径加到末尾
for(int i = 0; i < ans.size(); i++)
cout<<dire[ans[i]];
cout<<endl;
}
return 0;
}