BZOJ1671[Usaco2005 Dec]Knights of Ni 骑士 BFS

Posted CQzhangyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1671[Usaco2005 Dec]Knights of Ni 骑士 BFS相关的知识,希望对你有一定的参考价值。

[Usaco2005 Dec]Knights of Ni 骑士

Description

 贝茜遇到了一件很麻烦的事:她无意中闯入了森林里的一座城堡,如果她想回家,就必须穿过这片由骑士们守护着的森林.为了能安全地离开,贝茜不得不按照骑士们的要求,在森林寻找一种特殊的灌木并带一棵给他们.当然,贝茜想早点离开这可怕的森林,于是她必须尽快完成骑士们给的任务,贝茜随身带着这片森林的地图,地图上的森林被放入了直角坐标系,并按x,y轴上的单位长度划分成了W×H(1≤W,H≤1000)块,贝茜在地图上查出了她自己以及骑士们所在的位置,当然地图上也标注了她所需要的灌木生长的区域.某些区域是不能通过的(比如说沼泽地,悬崖,以及食人兔的聚居地).在没有找到灌木之前,贝茜不能通过骑士们所在的那个区域,为了确保她自己不会迷路,贝茜只向正北、正东、正南、正西四个方向移动(注意,她不会走对角线).她要走整整一天,才能从某块区域走到与它相邻的那块区域.    输入数据保证贝茜一定能完成骑士的任务.贝茜希望你能帮她计算一下,她最少需要多少天才可脱离这可怕的地方?

Input

    第1行输入2个用空格隔开的整数,即题目中提到的W、H.
    接下来输入贝茜持有的地图,每一行用若干个数字代表地图上对应行的地形.第1行描述了地图最北的那一排土地;最后一行描述的则是最南面的.相邻的数字所对应的区域是相邻的.如果地图的宽小于或等于40,那每一行数字恰好对应了地图上的一排土地.如果地图的宽大于40,那每行只会给出40个数字,并且保证除了最后一行的每一行都包含恰好40个数字.没有哪一行描述的区域分布在两个不同的行里.
    地图上的数字所对应的地形:
    0:贝茜可以通过的空地
    1:由于各种原因而不可通行的区域
    2:贝茜现在所在的位置
    3:骑士们的位置
    4:长着贝茜需要的灌木的土地

Output

    输出一个正整数D,即贝茜最少要花多少天才能完成骑士们给的任务.

Sample Input

8 4
4 1 0 0 0 0 1 0
0 0 0 1 0 1 0 0
0 2 1 1 3 0 4 0
0 0 0 4 1 1 1 0

INPUT DETAILS:

Width=8, height=4. Bessie starts on the third row, only a few squares away
from the Knights.

Sample Output

11

HINT

 这片森林的长为8,宽为4.贝茜的起始位置在第3行,离骑士们不远.

    贝茜可以按这样的路线完成骑士的任务:北,西,北,南,东,东,北,东,东,南,南.她在森林的西北角得到一株她需要的灌木,然后绕过障碍把它交给在东南方的骑士.

题解:双BFS,刷水有益健康。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#define ok(a,b)    (a>=1&&a<=w&&b>=1&&b<=h&&map[a][b]!=1)
using namespace std;
int map[1010][1010];
int w,h,ans,dis[1010][1010][2],inq[1010][1010],x1,x2,y1,y2;
int dir[][2]={{-1,0},{1,0},{0,1},{0,-1}};
queue <int> qx,qy;
int readin()
{
    int ret=0;    char gc;
    while(gc<0||gc>9)    gc=getchar();
    while(gc>=0&&gc<=9)    ret=ret*10+gc-0,gc=getchar();
    return ret;
}
void bfs(int x,int y,int t)
{
    dis[x][y][t]=0;
    qx.push(x),qy.push(y);
    int i,tx,ty;
    while(!qx.empty())
    {
        x=qx.front(),y=qy.front();
        qx.pop(),qy.pop();
        for(i=0;i<4;i++)
        {
            tx=x+dir[i][0],ty=y+dir[i][1];
            if(ok(tx,ty)&&dis[tx][ty][t]>dis[x][y][t]+1)
            {
                dis[tx][ty][t]=dis[x][y][t]+1;
                if(!inq[tx][ty])
                {
                    inq[tx][ty]=1;
                    qx.push(tx),qy.push(ty);
                }
            }
        }
        inq[x][y]=0;
    }
}
int main()
{
    h=readin(),w=readin();
    int i,j;
    for(i=1;i<=w;i++)
    {
        for(j=1;j<=h;j++)
        {
            map[i][j]=readin();
            if(map[i][j]==2)    x1=i,y1=j;
            if(map[i][j]==3)    x2=i,y2=j;    
        }
    }
    memset(dis,0x3f,sizeof(dis));
    bfs(x1,y1,0),bfs(x2,y2,1);
    ans=1<<30;
    for(i=1;i<=w;i++)
        for(j=1;j<=h;j++)
            if(map[i][j]==4)
                ans=min(ans,dis[i][j][0]+dis[i][j][1]);
    printf("%d",ans);
    return 0;
}

 

以上是关于BZOJ1671[Usaco2005 Dec]Knights of Ni 骑士 BFS的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ1672][Usaco2005 Dec]Cleaning Shifts 清理牛棚

bzoj1730[Usaco2005 dec]Barn Expansion 牛棚扩张

bzoj1672[Usaco2005 Dec]Cleaning Shifts 清理牛棚*

bzoj1692 cogs2005 jzoj1940: [Usaco2007 Dec]队列变换

bzoj 1731: [Usaco2005 dec]Layout 排队布局差分约束

BZOJ1729: [Usaco2005 dec]Cow Patterns 牛的模式匹配