您的位置:首页 > 其它

迷宫与宝藏

2016-07-11 16:50 232 查看


1646: 迷宫与宝藏

Time Limit:2000MS Memory Limit:65536KB

Total Submit:28 Accepted:10 Page
View:806
Submit Status Discuss


Description

机器人要在一个矩形迷宫里行动(不能原地停留,只能走向上/下/左/右),每移动一格花费1个单位时间。

迷宫有以下几种元素:
【*】 机器人的起点
【#】 墙。机器人不能走过这些格子
【.】 平地。机器人可以在上面自由行走
【0-9】 宝藏。当机器人走到此处会立刻获得该数字相应的宝藏,宝藏不会消失,可以反复获取(但不能停留)

若机器人要恰好获得总和为x的宝藏,它最少需要多少时间?



Input

第一行输入任务数量T, 接下来有T个任务
每块第一行有两个整数, n( < 100), m( < 100), 表示迷宫有n+1行和m+1列,输出迷宫地图。
最后一行输入你要收集的宝藏的总价值x(x ≤ 100)



Output

对于每个任务,输出最少花费的时间,如果完成不了该任务则输出-1


Sample
Input
Raw

3

2 3
1.#2
#..#
*.#.
3

2 3
2.#2
#..#
*.#.
5

2 3
2.#2
#.3#
*.#.
5


Sample
Output
Raw

8
-1
6



Tag

BFS 优先队列


一道比较需要三维标记的bfs,因为除墙以外的其他点都可以任意访问多次,所以需要三维标记VIS[x][y][val],前两维是坐标,最后一维是访问该点时所拥有的宝藏,当拥有不同的宝藏时可以访问同一个点。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int vis[105][105][105];
char a[105][105];
int c[4][2]={-1,0,1,0,0,-1,0,1};
struct L
{
int x,y,val,time;
};

int main()
{
int t,n,m,xx;
scanf("%d",&t);
while(t--)
{
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));
queue<L>q; //因为遇到足够宝藏的点时就会输出并跳出bfs,所以队列中可能会有上一轮中没有压出的数据,所以需要更新队列
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++)
{
scanf("%s",a[i]);
for(int j=0;j<=m;j++)
{
if(a[i][j]=='*')
{
L st;
st.x=i;
st.y=j;
st.time=0;
st.val=0;
vis[i][j][0]=1;
q.push(st);
}
}
}
scanf("%d",&xx);
int fg=0;
while(!q.empty())
{
L now=q.front();
q.pop();
if(now.val==xx)
{
printf("%d\n",now.time);
fg=1;
break;
}
if(now.val>xx) continue; //当宝藏的值已经大于需要值时就不用再压入其他点了,队列中所剩的点都是大于需要时,队列会压空,最后结束循环
for(int i=0;i<4;i++)
{
L next;
next.x=now.x+c[i][0];
next.y=now.y+c[i][1];
if(next.x>=0&&next.x<=n&&next.y>=0&&next.y<=m&&a[next.x][next.y]!='#')
{
if(vis[next.x][next.y][now.val]==0)
{
vis[next.x][next.y][now.val]=1;
if(a[next.x][next.y]<='9'&&a[next.x][next.y]>='0')
next.val=now.val+a[next.x][next.y]-'0'; //一定要减去‘0’才能转换为int
else next.val=now.val;
next.time=now.time+1;
q.push(next);
}
}
}
}
if(fg==0)
printf("-1\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  三维标记