找宝箱
Problem Description
作为一个强迫症患者,小 Y 在走游戏里的迷宫时一定要把所有的宝箱收集齐才肯罢休。现在给你一个 N *M 的迷宫,里面有障碍、空地和宝箱,小 Y 在某个起始点,每一步小 Y 可以往上下左右走,当然前提时没有走出迷宫并且走到的点不是障碍。如果小 Y 走到了某个为宝箱的点,那么这个宝箱就被他收集到了,然后此处变为空地。 现在你需要计算小 Y 最少需要走多少步才能收集齐所有的宝箱。
Input
输入包含多组数据。 对于每组数据,第一行两个正整数 N;M(1<=N;M<=100),表示迷宫大小。 接下来 N 行,每行 M 个整数,第 i + 1 行的第 j 个整数表示迷宫第 i 行第 j 列的情况,0 表示空地,-1表示障碍,1 表示宝箱,2 表示小Y 的起始点。保证2 只有一个,且宝箱数量不超过5 个。 数据以两个0 表示结尾。
Output
对于每组数据输出一行,包含一个整数,表示小 Y 最少的步数。如果小 Y 无法收集齐所有宝箱,输出-1。
Sample Input
3 5 1 -1 1 -1 2 0 -1 0 -1 0 0 0 0 0 0 0 0
#include<iostream>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
int map[105][105];
int ss[105][105];
int sr[8][8];
int m,n,cnt;
int dir[4][2]={{0,-1},{1,0},{0,1},{-1,0}};
bool isarea(int x,int y)
{
return x>=0&&x<m&&y>=0&&y<n;
}
struct ff{
int x;
int y;
};
ff f1[8];
struct lmx{
int x;
int y;
int step;
};
int bfs(int e,int w)
{
queue<lmx>q;
while(!q.empty()) q.pop();
int i,j;
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
map[i][j]=ss[i][j];
}
}
lmx s1,s2,s3;
s1.x=f1[e].x;
s1.y=f1[e].y;
s1.step=0;
q.push(s1);
map[s1.x][s1.y]=-1;
while(!q.empty())
{
s2=q.front();
q.pop();
for(i=0;i<4;i++)
{
s3.x=s2.x+dir[i][0];
s3.y=s2.y+dir[i][1];
if(map[s3.x][s3.y]!=-1&&isarea(s3.x,s3.y))
{
s3.step=s2.step+1;
q.push(s3);
map[s3.x][s3.y]=-1;
if(f1[w].x==s3.x&&f1[w].y==s3.y) return s3.step;
}
}
}
return -1;
}
int main()
{
int i,j,flag,sum,ce;
char sp[7]={"012345"};
while(cin>>m>>n)
{
cnt=1;
ce=10000;
sum=0;
flag=0;
if(m==0&&n==0) break;
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
cin>>ss[i][j];
if(ss[i][j]==2) {f1[0].x=i;f1[0].y=j;}
if(ss[i][j]==1) {f1[cnt].x=i;f1[cnt].y=j;cnt++;}
}
}
memset(sr,0,sizeof(sr));
for(i=0;i<cnt;i++)
{
for(j=0;j<cnt;j++)
{
if(i!=j) sr[i][j]=bfs(i,j);
if(sr[i][j]<0) { flag=1;break;}
}
if(flag) break;
}
if(flag)cout<<"-1"<<endl;
else
{
do{
sum=0;
for(i=0;i<cnt-1;i++)
{
sum+=sr[sp[i]-'0'][sp[i+1]-'0'];
}
if(sum<ce) ce=sum;
}while(next_permutation(sp+1,sp+cnt));
cout<<ce<<endl;
}
}
return 0;
}
为了明天所以选择坚定的执着今天。