迷宫与宝藏
Description
机器人要在一个矩形迷宫里行动(不能原地停留,只能走向上/下/左/右),每移动一格花费1个单位时间。迷宫有以下几种元素:【*】 机器人的起点【#】 墙。机器人不能走过这些格子【.】 平地。机器人可以在上面自由行走【0-9】 宝藏。当机器人走到此处会立刻获得该数字相应的宝藏,宝藏不会消失,可以反复获取(但不能停留)若机器人要恰好获得总和为x的宝藏,它最少需要多少时间?
Input
第一行输入任务数量T, 接下来有T个任务每块第一行有两个整数, n( < 100), m( < 100), 表示迷宫有n+1行和m+1列,输出迷宫地图。最后一行输入你要收集的宝藏的总价值x(x ≤ 100)
Output
对于每个任务,输出最少花费的时间,如果完成不了该任务则输出-1
3
2 3
1.#2
#..#
*.#.
3
1.#2
#..#
*.#.
3
2 3
2.#2
#..#
*.#.
5
2.#2
#..#
*.#.
5
2 3
2.#2
#.3#
*.#.
5
2.#2
#.3#
*.#.
5
8
-1
6
-1
6
这道题写了1天,奈何学艺不精,没A掉。用了DFS加BFS,内存爆了。
思路:感觉直接用BFS情况会比较复杂,于是我像用DFS从起点开始重新搜索一遍,搜索时传回最后一个节点宝藏的数值。如果没有则传回0,这样,就得到一张新的地图,有分支的地方即为有宝藏的地方,然后用bfs进行遍历。bfs的起点应该是所有根节点汇聚的点,在DFS的时候已找出,bfs遍历的同时,在找到一处宝藏之前。机器人不能回头,如果宝藏的数值超过给定大小,则continue。
目前没过,贴一下爆内存的代码:
#include<stdio.h>
#include<queue>
using namespace std;
char mp[50][50];
int use[50][50]= {0};
int use1[50][50]={0};
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
int p,n,m,ssx,ssy,tt=0;
struct node
{
int x;
int y;
int my;
int t;
int last;
};
int jud(int e)
{
if(e==0)return 1;
if(e==1)return 0;
if(e==2)return 3;
if(e==3)return 2;
}
int dfs(int sx,int sy)
{
node now,next;
now.x=sx;
now.y=sy;
use1[now.y][now.x]=1;
tt=0;
for(int i=0; i<4; i++)
{
next.x=now.x+dir[i][0];
next.y=now.y+dir[i][1];
if(next.x>=0&&next.x<m+1&&next.y>=0&&next.y<n+1&&(mp[next.y][next.x]>48&&mp[next.y][next.x]<=59)&&!use1[next.y][next.x])
{
use[now.y][now.x]+=dfs(next.x,next.y)+mp[next.y][next.x]-48;
if(use[now.y][now.x]!=use[next.y][next.x])
{
ssx=now.x;
ssy=now.y;
tt=0;
}
else tt++;
}
else if(next.x>=0&&next.x<m+1&&next.y>=0&&next.y<n+1&&mp[next.y][next.x]!='#'&&!use1[next.y][next.x])
{
use[now.y][now.x]+=dfs(next.x,next.y);
if(use[now.y][now.x]!=use[next.y][next.x])
{
ssx=now.x;
ssy=now.y;
tt=0;
}
else tt++;
}
}
return use[now.y][now.x];
}
int bfs(int sx,int sy)
{
queue<node>q;
node now,next;
now.x=sx;
now.y=sy;
now.my=0;
now.t=tt;
now.last=4;
q.push(now);
while(q.size())
{
now=q.front();
for(int i=0; i<4&&i!=now.last; i++)
{
next.x=now.x+dir[i][0];
next.y=now.y+dir[i][1];
if(next.x>=0&&next.x<m+1&&next.y>=0&&next.y<n+1&&(use[next.y][next.x]!=0||(mp[next.y][next.x]>48&&mp[next.y][next.x]<=59)))
{
next.t=now.t+1;
if(mp[next.y][next.x]>48&&mp[next.y][next.x]<=59)
{
next.my=now.my+mp[next.y][next.x]-48;
next.last=4;
}
else
{
if(mp[now.y][now.x]>48&&mp[now.y][now.x]<=59)next.last=4;
else next.last=jud(i);
next.my=now.my;
}
if(next.my>p)continue;
q.push(next);
}
if(next.my==p)break;
}
if(next.my==p)break;
q.pop();
}
if(q.size())return next.t;
else return -1;
}
int main()
{
int s,sx,sy,j;
scanf("%d",&s);
while(s--)
{
scanf("%d%d",&n,&m);
tt=0;
for(int i=0; i<n+1; i++)
scanf("%s",mp[i]);
scanf("%d",&p);
for(int i=0; i<n+1; i++)
{
for(j=0; j<m+1; j++)
{
use[i][j]=0;
use1[i][j]=0;
}
}
for(int i=0; i<n+1; i++)
{
for(j=0; j<m+1; j++)
if(mp[i][j]=='*')
{
sx=j;
sy=i;
break;
}
if(mp[i][j]=='*')break;
}
dfs(sx,sy);
printf("%d\n",bfs(ssx,ssy));
}
}