标签:
问题描述
输入
输出
样例输入
4 4 S.X. a.X. ..XG .... 3 4 S.Xa .aXB b.AG 0 0
样例输出
YES NO
题意:给你一个row * col的迷宫,‘.’表示可走的空地,‘X’表示不可走的围墙,‘S’表示起点,‘G’表示宝藏的地点(终点),‘A‘~‘E‘分别表示5种类型的门,‘a‘~‘e‘分别对应表示5种类型门的钥匙。要想打开某种类型的门,只有拿到了迷宫内其对应的所有钥匙。问你最终能不能拿到这份宝藏?
思路:刚开始深搜一直TLE 然后换了个广搜== 悲剧的是广搜又TLE了
最后经大神指导发现如果无路可走了而且在门打不开的情况下会有死循环 。。。。
#include <iostream>
#include <queue>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long LL;
const LL INF = 0xfffffff;
const int maxn = 50;
const LL MOD = 1e9+7;
char str[maxn][maxn];
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}}, ok;
int n, m, count_num[maxn], vis[maxn][maxn], sx, sy;
/**< count_num 钥匙的数量 vis标记 */
struct da
{
int x, y;
};
int bfs()
{
queue<da>Q;
da q, w;
q.x = sx, q.y = sy;
Q.push(q);
int time = 0;/**< n,m 都是小于20的 用time来限制时间 */
while(!Q.empty()&& time < 1000)
{
q = Q.front();
Q.pop();time++;
if(str[q.x][q.y] >= ‘A‘ && str[q.x][q.y] <= ‘E‘)
{
if(count_num[str[q.x][q.y]-‘A‘+1] == 0)/**< 如果是门并且钥匙够了 可以走 */
vis[q.x][q.y] = 1;
else /**< 否则就不能走 */
{
// count_num[str[q.x][q.y]-‘A‘+1]--;
Q.push(q);
continue;
}
}
for(int i = 0; i < 4; i++)
{
w = q;
w.x += dir[i][0];
w.y += dir[i][1];
if(w.x >=1 && w.x <= n && w.y >= 1 && w.y <= m && !vis[w.x][w.y])
{
if(str[w.x][w.y] == ‘G‘) return 1;
if(str[w.x][w.y] >= ‘A‘ && str[w.x][w.y] <= ‘E‘)
Q.push(w);
if(str[w.x][w.y] >= ‘a‘ && str[w.x][w.y] <= ‘e‘)
{
count_num[str[w.x][w.y]-‘a‘+1] --;/**< 找到一个钥匙 开这个门所需要的钥匙就-1 */
vis[w.x][w.y] = 1;
Q.push(w);
}
if(str[w.x][w.y] == ‘.‘)
{
vis[w.x][w.y] = 1;
Q.push(w);
}
}
}
}
return 0;
}
int main()
{
int i, j;
while(scanf("%d %d", &n, &m), n+m)
{
ok = 0;
memset(count_num, 0, sizeof(count_num));
memset(vis, 0, sizeof(vis));
for(i = 1; i <= n; i++)
{
scanf("%s", str[i]+1);
for(j = 1; j <= m; j++)
{
if(str[i][j] >= ‘a‘ && str[i][j] <= ‘e‘)
count_num[str[i][j]-‘a‘+1] ++;
if(str[i][j] == ‘S‘)
sx = i, sy = j;
}
}
vis[sx][sy] = 1;
ok = bfs();
if(ok) printf("YES\n");
else printf("NO\n");
}
return 0;
}
标签:
原文地址:http://www.cnblogs.com/PersistFaith/p/4832417.html