P2658 汽车拉力比赛 - 普及+/提高-二分+搜索

P2658 汽车拉力比赛

在这里插入图片描述
思路:刚开始我就写了一个把路标的四个方向最小的值 的 最大值输出来,答案就能得到90分哈哈哈,但这是不正确的做法 还是AC不了!
自己也是没做出来 。
这个题用到了搜索+二分法 太厉害了吧
首先二分怎么用的r取所有坐标的最大值,然后l去0,然后利用mid来判断 这个值 是不是 小于等于 遍历那几个点所经过的最大的坐标差?
然后再讲bfs怎么搜索的
题目说了四个方向,先写出来四个方向的数组。
然后在bfs中 先从起点开始,设立两个队列来储存刚才走的点,如果访问过了就把状态数组v设为1;然后什么叫访问一遍了就是 直到队列元素为空
每次都用front元素,然后进行四个方向的模拟,如果这个方向所走的差<=mid 那么你就可以把这点放进队列!!!然后再进行访问,每次都记得访问到1的地方要累加,等着访问到sum个1 就结束任务了!!!!!

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <algorithm>
#include <iomanip>
#include <map>
#include <queue>
#include <vector>
#include <set>
const int inf = 0x3f3f3f3f;//1061109567
typedef long long ll;
using namespace std;
int a[505][505],b[505][505];
int l, r, mid, sum, qx, qy;
//四个方向
int dx[5] = { 0,0,1,0,-1 };
int dy[5] = { 0,1,0,-1,0 };
int v[505][505];
int ans; int m, n;
int f()
{
    queue<int>x, y;
    int vist = 1;
    x.push(qx), y.push(qy);
    v[qx][qy] = 1;
    while (!x.empty() && !y.empty())
    {
        if (vist == sum) return 1;
        int lx, ly;
        lx = x.front(); ly = y.front();
        x.pop(), y.pop();
        for (int i = 1; i <= 4; i++)
        {
            int nx = lx + dx[i];
            int ny = ly + dy[i];
            if (nx <1|| nx > n ||ny <1||ny > m||v[nx][ny])
                continue;
            if (fabs(a[nx][ny]-a[lx][ly]) > mid)
                continue;
            else
            {
                if (b[nx][ny]==1) vist++;
                x.push(nx), y.push(ny);
                v[nx][ny] = 1;
            }
        }
    }
    return 0;
}
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
        {
            cin >> a[i][j];
            r = max(r, a[i][j]);
        }
    int sign = 0;
    for (int i = 1; i <=n; i++)
        for (int j = 1; j <= m; j++)
        {
            cin >> b[i][j];
            if (sign == 0 && b[i][j] == 1)
            {
                qx = i; qy = j; sign = 1;
            }
            if (b[i][j] == 1)
                sum++;
        }
    while (l <= r)
    {
        mid = (l + r) / 2;
        memset(v, 0, sizeof v);
        if (f())
        {
            r = mid - 1; ans = mid;
        }
        else l = mid + 1;
    }
    cout << ans << endl;
}


      
            
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值