训练第二周之BFS例题

1、迷宫问题-百练10

思路:讲到bfs例题,当然是迷宫问题最经典
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
struct position
{
    int x,y;//x坐标,y坐标
};
typedef struct position Node;
bool visit[6][6]={0};//判断是否为白色节点
int state[6][6];//输入迷宫状态
Node ans[25][25];//记录所到节点*前一步*的坐标
bool isValid(Node vw)//判断该位置是否合法
{
    if(vw.x<0||vw.x>4||vw.y<0||vw.y>4)//是否在迷宫内
        return false;
    if(state[vw.x][vw.y]==1)//是否是墙壁
        return false;
    return true;
}
bool bfs(Node vs,Node vd)//宽度优先搜索
{
    queue<Node> q;//建立队列
    Node vn,vw;
    int move[4][4]={{-1,0},{1,0},{0,-1},{0,1}};//有四种移动
    memset(visit,false,sizeof(visit));
    q.push(vs);//将起点加入队列
    visit[vs.x][vs.y]=1;//将起点变成灰色
    while(!q.empty())
    {
        vn=q.front();//将队列头抽出
        q.pop();//将该节点变黑(踢出队列)
        for(int i=0;i<4;i++)
        {
            vw.x=vn.x+move[i][0];
            vw.y=vn.y+move[i][1];

            if(vw.x==vd.x&&vw.y==vd.y)
            {
                ans[vw.x][vw.y]=vn;//将前一步的坐标赋给ans[vw.x][vw.y]
                return true;
            }
            if(isValid(vw)&&!visit[vw.x][vw.y])
            {
                q.push(vw);//加入队列
                ans[vw.x][vw.y]=vn;//记录前一步
                visit[vw.x][vw.y]=1;//将该节点变灰
                //printf("%d %d %d\n",vw.x,vw.y,vw.sum);
            }
        }
    }
    return false;
}
void road(Node vd)//输出路径
{
    stack<Node> s;//建立栈
    Node vw;
    vw.x=vd.x;
    vw.y=vd.y;
    while(vw.x!=0||vw.y!=0)//不到达起点就一直放
    {
        s.push(vw);//加入栈
        vw=ans[vw.x][vw.y];//把前一步的坐标赋给该节点
    }
    printf("(0, 0)\n");
    while(!s.empty())
    {
        vw=s.top();//抽栈头
        s.pop();//移除该节点
        printf("(%d, %d)\n",vw.x,vw.y);
    }
    return;
}
int main(){
    int i,j;
    Node vs,vd;
    for(i=0;i<5;i++)
        for(j=0;j<5;j++)
            scanf("%d",&state[i][j]);
    vs.x=0;
    vs.y=0;
    vd.x=4;
    vd.y=4;
    bfs(vs,vd);
    road(vd);
    return 0;
}

2、红与黑-百练2816

思路:这题比较简单,就从起点开始搜索过去,遇到黑就走,白不走,每走一步sum+1
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
char state[25][25];
bool visit[25][25];
int sum=1;//记录所走的黑瓷砖总数
int w,h;
struct Node
{
    int x,y;
};
bool isValid(Node vw,int w,int h)//判断vw是否合法
{
    if(vw.x<0||vw.x>=h||vw.y<0||vw.y>=w)
        return false;
    if(state[vw.x][vw.y]!='.')
        return false;
    return true;
}
void bfs(Node vs,int w,int h)
{
    queue<Node> q;
    memset(visit,false,sizeof(visit));
    Node vw,vn;
    int move[4][4]={{-1,0},{1,0},{0,-1},{0,1}};
    q.push(vs);
    visit[vs.x][vs.y]=1;
    while(!q.empty())//一步步过去直到队列为空
    {
        vn=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            vw.x=vn.x+move[i][0];
            vw.y=vn.y+move[i][1];
            //printf("%d %d %d %d\n",vw.x,vw.y,w,h);
            if(isValid(vw,w,h)&&!visit[vw.x][vw.y])
            {
                sum+=1;
                q.push(vw);
                visit[vw.x][vw.y]=1;
            }
        }
    }
    return;
}
int main()
{
    int i,j;
    Node vs;
    while(scanf("%d%d",&w,&h)!=EOF&&w&&h)
    {
        sum=1;
        memset(state,0,sizeof(state));
        for(i=0;i<h;i++)
            scanf("%s",state[i]);
        for(i=0;i<h;i++)//找到起点
            for(j=0;j<w;j++)
            if(state[i][j]=='@')
            {
                vs.x=i;
                vs.y=j;
            }
        bfs(vs,w,h);
        printf("%d\n",sum);
    }
    return 0;
}

3、Knight Moves-百练

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int ans[305][305];//记录 knight moves
bool visit[305][305];//标记为灰色节点
int Move[8][8]={{-2,1},{-1,2},{1,2},{2,1},
                {2,-1},{1,-2},{-1,-2},{-2,-1}};//八种移动。这里move小写就CE了,不懂。。。

struct node
{
    int x,y;
};
bool isValid(node vw,int l)
{
    if(vw.x<0||vw.x>=l||vw.y<0||vw.y>=l)
        return false;
    return true;
}
void bfs(node vs,node vd,int l)
{
    queue<node> q;
    node vn,vw;
    memset(visit,false,sizeof(visit));
    memset(ans,0,sizeof(ans));
    q.push(vs);
    visit[vs.x][vs.y]=1;
    while(!q.empty())
    {
        vn=q.front();
        q.pop();
        for(int i=0;i<8;i++)
        {
            vw.x=vn.x+Move[i][0];
            vw.y=vn.y+Move[i][1];
            if(vw.x==vd.x&&vw.y==vd.y)//是否到达终点
            {
                ans[vd.x][vd.y]=ans[vn.x][vn.y]+1;
                //printf("%d\n",ans[vd.x][vd.y]);
                return;
            }
            if(isValid(vw,l)&&!visit[vw.x][vw.y])//判断vw是否合法且为白色节点
            {
                ans[vw.x][vw.y]=ans[vn.x][vn.y]+1;
                q.push(vw);
                visit[vw.x][vw.y]=1;
                //printf("%d %d %d\n",vw.x,vw.y,ans[vw.x][vw.y]);
            }
        }
    }
    return;
}
int main()
{
    int n,l,x1,y1,x2,y2;
    node vs,vd;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d",&l);
        scanf("%d%d",&x1,&y1);
        scanf("%d%d",&x2,&y2);
        vs.x=x1;
        vs.y=y1;
        vd.x=x2;
        vd.y=y2;
        //printf("%d %d %d %d\n",vs.x,vs.y,vd.x,vd.y);
        if(vs.x==vd.x&&vs.y==vd.y)//起点终点相同直接输出0
            printf("0\n");
        else
        {
            bfs(vs,vd,l);
            printf("%d\n",ans[vd.x][vd.y]);
        }
    }
    return 0;
}

4、Catch That Cow-杭电2717

代码:

#include<stdio.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<queue>
using namespace std;
#define way3(x) x*2
struct node
{
    int x;
};
typedef struct node Node;
int sum[100005]={0};
bool visit[100005];
bool limit(int x)
{
    if(x>=0&&x<=100000)
        return true;
    return false;
}
bool bfs(Node vs,Node vd)
{
    Node vw,vn;
    queue<Node> q;
    int i;
    memset(visit,false,sizeof(visit));
    memset(sum,0,sizeof(sum));
    q.push(vs);
    visit[vs.x]=true;
    int way[2]={-1,1};
    while(!q.empty())
    {
        vn=q.front();
        q.pop();
        for(i=0;i<2;i++){
            vw.x=vn.x+way[i];
            if(vw.x==vd.x)
            {
                sum[vd.x]=sum[vn.x]+1;
                return true;
            }
            if(limit(vw.x)&&!visit[vw.x])
            {
                q.push(vw);
                visit[vw.x]=1;
                sum[vw.x]=sum[vn.x]+1;
            }
        }
        vw.x=way3(vn.x);
        if(vw.x==vd.x)
        {
            sum[vd.x]=sum[vn.x]+1;
            return true;
        }
        if(limit(vw.x)&&!visit[vw.x])
        {
            q.push(vw);
            visit[vw.x]=1;
            sum[vw.x]=sum[vn.x]+1;
        }
    }
    return false;
}
int main(){
        Node N,K;
    while(scanf("%d%d",&N.x,&K.x)!=EOF){
        //scanf("%d%d",&N.x,&K.x);
        if(N.x>=K.x)//已经在牛的后面就不能再乘以2了只要相减
            printf("%d\n",N.x-K.x);
        else{
            bfs(N,K);
            printf("%d\n",sum[K.x]);
        }
    }
    return 0;
}

感受:

感觉bfs的题目都比较僵硬,只要找到起点然后一步步搜索过去就行,感觉大多时候是在套模板,可能是我还没遇到较难的题吧。。。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值