http://119.23.43.230/problem.php?id=1234
题目描述
小z喜欢上了一个迷宫游戏,这个游戏是这样的,有一个N*M的迷宫(即N行M列的迷宫)保证0<N<=500,0<M<=500
左上角坐标(1,1)为入口,右下角坐标(N,M)为出口,这个迷宫和一般迷宫不同的地方是,
迷宫种可能会出现k个宝石(0<=k<=3),小z如果获得这些宝石那么在走到出口后就会有奖励,
同时游戏完成的出色程度也和小z走的步数有关,步数越小,奖励就越丰厚。
小z把迷宫的地图给你,想知道在尽可能获得更多的宝石的情况下,走出迷宫所需的最小步数是多少?如果无法走到出口,那么答案就是-1
输入
不会有多组输入数据
第一行两个整数N M,代表迷宫的行数和列数(N M中间以空格隔开)
之后N行每行M个数,每行的数之间用空格隔开,代表迷宫的地图
下面说一下地图元素的表示方法:
设A[i,j]为地图第i行第j列的元素
如果A[i,j]等于 -1 即代表地图第i行 第j列为障碍,不可到达,不可通过
如果A[i,j]不等于-1那么这个位置就是合法位置,玩家可以到达和通过
当然在i<0,j<0,i>N或者j>M这些情况下,坐标(i,j)已经超过了地图的边界,是不合法的
如果A[i,j]等于1、2或3,那么就代表(i,j)位置存在宝石,玩家走到该位置就自动获得这颗宝石
输出
输出只有一个整数,即所求答案
答案为在尽可能获得更多的宝石的情况下,走出迷宫所需的最小步数
如果无法走到出口,那么答案就是-1
样例输入
3 3
0 -1 1
0 0 0
0 -1 0
样例输出
6
思路 :这是一个状压bfs ,先dfs一遍是否能拿宝石,可以拿几个宝石。
宝石最多有3个 ,可以在001 表示只能1号宝石,010表示拿2号。100表示拿3号宝石
111表示全拿。用vis【】【】【】标记表示x,y,已经宝石拿的数量,进行bfs。
与hdu5094相似,比hdu5094简单
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int>P;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int M = 1e6 + 10;
int n,m;
int res=0;
int maps[510][510];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,-1,1};
bool vis[510][510][1<<4],vis1[510][510];
int jewel[510][510];
struct node
{
int x,y,step,j,ans;
node(){}
node(int xx,int yy,int s,int jj,int as)
{
x=xx;y=yy;step=s;j=jj;ans=as;
}
};
bool check(int x,int y)
{
if(x<1||x>n||y<1||y>m)
return 0;
else
return 1;
}
void bfs1()
{
queue<P>q;
P p;
p.first=1;
p.second=1;
vis1[1][1]=1;
if(maps[1][1]>0)
res++;
q.push(p);
while(q.size())
{
P pp=q.front();
q.pop();
// cout<<pp.first<<" "<<pp.second<<endl;
for(int i=0;i<4;i++)
{
int xx=pp.first+dx[i],yy=pp.second+dy[i];
if(!check(xx,yy))
continue;
if(!vis1[xx][yy])
{
if(maps[xx][yy]==-1)
continue;
vis1[xx][yy]=1;
p.first=xx;
p.second=yy;
if(maps[xx][yy]>0)
res++;
q.push(p);
}
}
}
}
int bfs()
{
memset(vis,0,sizeof(vis));
queue<node>q;
int s;
s=maps[1][1]>0?1:0;
q.push(node(1,1,0,jewel[1][1],s));
while(q.size())
{
node k=q.front();
q.pop();
int x=k.x,y=k.y,s=k.step,j=k.j,sum=k.ans;
//cout<<x<<" "<<y<<" "<<sum<<" "<<j<<" "<<k.step<<" "<<res<<endl;
if(x==n&&y==m&&sum==res)
return s;
for(int i=0;i<4;i++)
{
int xx=x+dx[i],yy=y+dy[i],jj=j;
int ok = 0;
if(maps[xx][yy]>0&& (jj&(jewel[xx][yy]))==0){
ok=1;
jj=jj|jewel[xx][yy];
}
if(!check(xx,yy))
continue;
if(maps[xx][yy]==-1||vis[xx][yy][jj])
continue;
vis[xx][yy][jj]=1;
q.push(node(xx,yy,s+1,jj,sum+ok));
}
}
return -1;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
//FILE *out = fopen("D:\\maps.txt","w+");
memset(maps,0,sizeof(maps));
memset(jewel,0,sizeof(jewel));
memset(vis1,0,sizeof(vis1));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&maps[i][j]);
if(maps[i][j]>0)
{
jewel[i][j]=(1<<(maps[i][j]-1));
}
}
}/*
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(maps[i][j]!=-1)
fprintf(out,"%d ",maps[i][j]+1);
else
fprintf(out,"%d ",0);
}
fprintf(out,"\n");
}
fclose(out);*/
res=0;
bfs1();
//cout<<res<<endl;
int ans=bfs();
printf("%d\n",ans);
}
return 0;
}