zoukankan      html  css  js  c++  java
  • 题解 【洛谷P1332】血色先锋队

    题面:https://www.luogu.org/problemnew/show/P1332

    很容易看出,这是一个典型的广度优先搜索,也就是众多OIer口中的bfs。

    先给各位普及一下bfs(部分来自百度):

    广度优先搜索(Breadth-First Search),又称作宽度优先搜索,或横向优先搜索,简称bfs,是一种基础算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点,如果发现目标,则演算终止。广度优先搜索的实现一般采用队列。

    其实,广度优先搜索是搜索算法的基础,想要成为一名优秀的OIer,广度优先搜索和深度优先搜索都是必须掌握的!

    此题告诉了我们有A个感染源,B个领主,我们可以定义一个vis数组,若当前坐标的vis值为1,那么此处就没有被感染;否则,当前坐标就已被感染。

    我们可以首先用bfs算出每个坐标被感染的时间,最后直接输出领主被感染的时间即可。

    话不多说,上代码:

    #include<bits/stdc++.h>//万能头文件
    using namespace std;//开启标准名字空间
    struct Node
    {
        int x,y,Time;//x为横坐标,y为纵坐标,Time为被感染时间
    } s[250010];//设置结构体数组维护队列
    int head,tail;//分别为头指针、尾指针
    int n,m,a,b,vis[505][505],c[250010],d[250010],e,f,i,j,
        k;//vis的意义同分析,c数组和d数组为感染源坐标,e、f为领主坐标
    int P[510][510];//每个坐标被感染时间
    void bfs()  //开始bfs
    {
        tail=0;
        head=0;//初始化指针
        for(i=1; i<=a; i++)  //先把已知条件加入队列,并初始化时间
        {
            s[++tail].x=c[i];//相当于tail++,s[tail].x=c[i]
            s[tail].y=d[i];
            s[tail].Time=0;
            P[c[i]][d[i]]=0;
        }
        while(head<tail)  //如果队列中还有元素
        {
            head++;//头指针加1
            int h=s[head].x,r=s[head].y,tmp=s[head].Time;//取出队首元素
            if(h+1<=n && vis[h+1][r]==0)  //往右扩展,若合法加入队列
            {
                s[++tail].x=h+1;//更新x坐标
                s[tail].y=r;//更新y坐标
                P[h+1][r]=s[tail].Time=tmp+1;//更新时间
                vis[h+1][r]=1;//记录为已被感染
            }
            //以下每步操作意义同上
            if(h-1>=1 && vis[h-1][r]==0)  //往左扩展,若合法加入队列
            {
                s[++tail].x=h-1;
                s[tail].y=r;
                P[h-1][r]=s[tail].Time=tmp+1;
                vis[h-1][r]=1;
            }
            if(r+1<=m && vis[h][r+1]==0)  //往上扩展,若合法加入队列
            {
                s[++tail].x=h;
                s[tail].y=r+1;
                P[h][r+1]=s[tail].Time=tmp+1;
                vis[h][r+1]=1;
            }
            if(r-1>=1 && vis[h][r-1]==0)  //往下扩展,若合法加入队列
            {
                s[++tail].x=h;
                s[tail].y=r-1;
                P[h][r-1]=s[tail].Time=tmp+1;
                vis[h][r-1]=1;
            }
        }
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&a,&b);//输入矩阵大小、感染源个数和领主个数
        for(i=1; i<=a; i++)
        {
            scanf("%d%d",&c[i],&d[i]);//输入感染源坐标
            vis[c[i]][d[i]]=1;//记录为已被感染
        }
        bfs();//遍历每个坐标被感染的时间
        for(i=1; i<=b; i++)
        {
            scanf("%d%d",&e,&f);//输入领主坐标
            printf("%d\n",P[e][f]);//直接输出被感染时间
        }
        return 0;//结束
    }

    有些人直接枚举每一个领主和感染源,求他们曼哈顿距离,但在矩阵过大时会TLE,所以bfs总是比暴力好的。

  • 相关阅读:
    UVALive 7509 Dome and Steles
    HDU 5884 Sort
    Gym 101194H Great Cells
    HDU 5451 Best Solver
    HDU 5883 The Best Path
    HDU 5875 Function
    卡特兰数
    UVa 11729 Commando War 突击战
    UVa 11292 The Dragon of Loowater 勇者斗恶龙
    Spark Scala Flink版本对应关系
  • 原文地址:https://www.cnblogs.com/xsl19/p/10414735.html
Copyright © 2011-2022 走看看