poj2110

题意:给定一个矩阵,从左上角到右下角,使走过的路径中数字的最大值最小值之差最小,问差最小是多少。

分析:首先不能用bfs,priority_queue以下两组数据可以说明问题。

有时候不能先扩展最优的。

2
5 6
1 1


3
5 6 1
1 3 5
1 7 1

正确的方法是二分这个差值a,对于每个二分结果枚举范围d~d+a,然后进行bfs,只有矩阵上的数字在d到d+a之间的格子才可以走。看能否到达终点。

View Code
#include <iostream>
#include
<cstdio>
#include
<cstdlib>
#include
<cstring>
using namespace std;

#define maxn 115

struct Node
{
int x, y;
} q[maxn
* maxn];

int n, u, d;
int map[maxn][maxn];
bool vis[maxn][maxn];
int dir[4][2] =
{
{
1, 0 },
{
0, 1 },
{
-1, 0 },
{
0, -1 } };

void input()
{
u
= 0;
d
= maxn;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
{
scanf(
"%d", &map[i][j]);
d
= min(map[i][j], d);
u
= max(map[i][j], u);
}
}

bool ok(Node &a, int u, int d)
{
if (a.x < 0 || a.y < 0 || a.x >= n || a.y >= n)
return false;
return !vis[a.x][a.y] && map[a.x][a.y] <= u && map[a.x][a.y] >= d;
}

bool bfs(int d, int u)
{
q[
0].x = 0;
q[
0].y = 0;
int front = 0;
int rear = 1;
memset(vis,
0, sizeof(vis));
vis[
0][0] = true;
while (front != rear)
{
Node temp
= q[front++];
if (front == maxn * maxn)
front
= 0;
for (int i = 0; i < 4; i++)
{
Node a;
a.x
= temp.x + dir[i][0];
a.y
= temp.y + dir[i][1];
if (ok(a, u, d))
{
q[rear
++] = a;
if (rear == maxn * maxn)
rear
= 0;
vis[a.x][a.y]
= true;
}
}
}
return vis[n - 1][n - 1];
}

bool reach(int a)
{
for (int i = max(max(d, map[n - 1][n - 1] - a), map[0][0] - a); i <= min(
min(u
- a, map[0][0]), map[n - 1][n - 1]); i++)
if (bfs(i, i + a))
return true;
return false;
}

void binarysearch()
{
int l = abs(map[n - 1][n - 1] - map[0][0]);
int r = u - d;
while (l < r)
{
int mid = (l + r) / 2;
if (reach(mid))
r
= mid;
else
l
= mid + 1;
}
printf(
"%d\n", l);
}

int main()
{
//freopen("t.txt", "r", stdin);
scanf("%d", &n);
input();
binarysearch();
return 0;
}

你可能感兴趣的:(poj)