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;
}