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<cstring>
#include<stdio.h>
#include<queue>
#include<algorithm>
using namespace std;
const int M=;
int n,m;
int map[M][M]; //迷宫
struct point
{
int r;
int l;
} p[]; //记录宝箱位置和初始位置
int run[][]= {,,-,,,,,-}; //bfs的方向数组
int bfs(point x,point y) //求两个宝箱的最短距离
{
int r,l,i,now,next,a[M][M]= {},mp[M][M];
queue<int> qu;
now=x.r*m+x.l;
qu.push(now);
for(i=; i<n; i++) //因为要调用计算多次,所以map不能改变,每次用map 初始mp
for(l=; l<m; l++)
mp[i][l]=map[i][l];
while(!qu.empty())
{
now=qu.front();
qu.pop();
for(i=; i<; i++)
{
r=now/m+run[i][];
l=now%m+run[i][];
next=r*m+l;
if(r>= &&r<n && l>= && l<m && mp[r][l]!=-)
{
a[r][l]+=a[now/m][now%m]+;
qu.push(next);
mp[r][l]=-;
if(r==y.r && l==y.l)
return a[r][l];
}
}
}
return -; //不通时返回
}
int main()
{
freopen("a.txt","r",stdin);
int i,j,num,min,dis[M][M];//dis数组保存第i个宝箱到第j个宝箱的最短距离
while(scanf("%d%d",&n,&m)!=EOF && n!= && m!=)
{
memset(dis,,sizeof(dis));
int flag=;//若有宝箱不能到达的标志
min=;
num=;
for(i=; i<n; i++)
for(j=; j<m; j++)
{
cin>>map[i][j];
if(map[i][j]==)
{
p[].r=i;
p[].l=j;
}
if(map[i][j]== )
{
p[num].r=i;
p[num++].l=j;
}
}
for(i=; i<num; i++)
{
for(j=; j<num; j++)
if(i!=j)
{
dis[i][j]=bfs(p[i],p[j]);
if(dis[i][j]==-)
{
flag=;
break;
}
}
if(flag)
break;
}
if(flag)
{
printf("-1\n");
continue;
}
char a[]= {""};
//因为最多有5个宝箱,用这个字符串代表排列的顺序,看下面会懂的,有点妙!
do
{
int s=;
for(i=; i<num-; i++)
{
s+=dis[a[i]-''][a[i+]-''];
}
if(min>s) //判断每种情况,
min=s;
}
while(next_permutation(a+,a+num));
//一个库函数 第一次经过他之后a[6]={"02354"}
printf("%d\n",min);
}
return ;
}

最新文章

  1. Redis-Sentinel(Redis集群监控管理)
  2. python import cv2 出错:cv2.x86_64-linux-gnu.so: undefined symbol
  3. 获取MySQL服务提供的sakila数据库(Example Databases)
  4. RAD 版本迁移工具,不怕升级麻烦了。
  5. 当freemarker中EL表达式的值为空时出现异常的解决方法
  6. markdown文本转换word,pdf
  7. ajax csrf
  8. Yii easyWechat 开发的时候报错:cURL error 60: SSL certificate problem: unable to get local issuer certificat
  9. IIS Express 域认证问题(https://stackoverflow.com/questions/4762538/iis-express-windows-authentication)
  10. Scala-Unit-2-Scala基础语法1
  11. Zookeeper应用之——栅栏(barrier)
  12. 高德地图JS API 开发小结
  13. 关于Unity中如何判断一个动画播放结束
  14. 51单片机的idata,xdata,pdata,data的详解(转)
  15. jmeter java请求:java.lang.VerifyError: Cannot inherit from final class
  16. 41:和为S的两个数
  17. 示例 - 如何在Console应用程序中应用SpiderStudio生成的DLL?
  18. Machine Learning笔记整理 ------ (三)基本性能度量
  19. SQL中的聚合函数
  20. redis 集群 搭建

热门文章

  1. spark 学习路线及参考课程
  2. iOS Programming UISplitViewController
  3. iOS循环引用
  4. sql语句中截取字符串
  5. JS性能分析(测试代码运行时间)
  6. 新手写的一个DBCP工具类
  7. Mysql基本操作、C++Mysql简单应用、PythonMysql简单应用
  8. 大项目之网上书城(九)——订单Demo
  9. 样例GeoQuiz应用开发 第1章
  10. jenkins构建项目记录1