码迷,mamicode.com
首页 > 其他好文 > 详细

找宝箱 (bfs)

时间:2015-05-31 23:01:49      阅读:280      评论:0      收藏:0      [点我收藏+]

标签:

 

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

 

找宝箱 (bfs)

标签:

原文地址:http://www.cnblogs.com/nowandforever/p/4542689.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!