bfs&dfs

bfs模版题

题目1:Catch That Cow

题意:直线上从n点移动到k点需要多少时间,共有3中移动方式(假设当前位置是x):

1.移动到左边(x-1)

2.移动到右边(x+1)

3.移动到2*x

每种移动所需的时间都是1分钟。

思路:bfs搜索,从每一个当前状态x最多都可以扩展出三个状态:x-1 、x+1、2*x,当bfs到终点k的时候结束。

代码:

#include<iostream>
#include<queue>
#include<cstdio>
#include<cmath>
#include<vector>
#include<cstring>
#define ll long long
using namespace std;

const int M=1e5+100,fin=1e8;

int a[M];

void bfs(int n,int k)
{
    int c;
    fill(a,a+M,fin);
    queue<int> q;
    q.push(n);
    q.push(0);
    while(!q.empty())
    {
        n=q.front();
        q.pop();
        c=q.front();
        q.pop();
        if(c>=a[n])continue;
        a[n]=c;
        for(int i=-1; i<=1; i+=2)
            if(0<=(i+n)&&(i+n)<=M)
            {
                q.push(i+n);
                q.push(c+1);
            }
        if(0<=(2*n)&&(2*n)<=M)
        {
            q.push(2*n);
            q.push(c+1);
        }
    }
}

int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    bfs(n,k);
    printf("%d\n",a[k]);
    return 0;
}

 

题目2

思路:使用bfs进行搜索,从当前点最多可以扩展出4个点(4个方向),某个点可能会多次被扩展到,取其中最小的即可。

代码:

#include<iostream>
#include<queue>
#include<cstdio>
#include<cmath>
#include<vector>
#include<cstring>
#define ll long long
using namespace std;

const int M=120,fin=1e8;

int a[M][M],n,v[M][M],dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};

bool in(int x,int y)
{
    if(1<=x&&x<=n&&1<=y&&y<=n)return true;
    else return false;
}

int bfs(int x,int y)
{
    int st;
    for(int i=1;i<=n;i++)fill(v[i]+1,v[i]+n+1,fin);
    queue<int> q;
    q.push(x);
    q.push(y);
    q.push(a[x][y]);

    while(!q.empty())
    {
        x=q.front();q.pop();
        y=q.front();q.pop();
        st=q.front();q.pop();
        if(st>=v[x][y])continue;
        v[x][y]=st;
        for(int i=0;i<4;i++)
        {
            int tx=x+dir[i][0],ty=y+dir[i][1];
            if(a[tx][ty]&&in(tx,ty))
            {
                q.push(tx);
                q.push(ty);
                q.push(st+a[tx][ty]);
            }
        }
    }
    return v[n][n];
}

int main()
{
    while(scanf("%d",&n)==1)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            scanf("%d",&a[i][j]);
        printf("min=%d\n",bfs(1,1));
    }
    return 0;
}

使用bfs来求最值小值的时候,如果第一次到达某一点的答案就是最小值(也就是说以后到达该点的值都比第一次大)那么就可以用例题1中的模版,当从队列中出来的点就是终点的时候就可以返回了。

   但如果第一次到达某一点的值不一定是最小值的话,就不能用例题1中的模版,应该使用例题2中的模版,即用bfs搜索所有的可能结果,从中取最优值。当搜索到某一点的时候判断这一次的值是否比上一次的值更优,如果更优才会扩展他后面的点,否则忽略(剪枝)。初始值为最大值。

   其实第二种方法就已经包括了第一中方法,但是效率没有第一种高。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值