最近好忙,好久没有更新- -水题做太多了。。。。。
2110是一个很好的搜索题。解法就是枚举最小值,任何二分区间,再暴力bfs。直接宽搜是肯定不行的。
看这个博客里面给的两个数据就知道了。http://www.cnblogs.com/rainydays/archive/2011/07/20/2111404.html
然后做法就跟普通宽搜类似了,只要判断每个位置上的值是不是在区间内,如果在就加入队列。否则排除。如果是强一点的数据这样可能就超时了。但是这个题没有。所以知道出题者的想法很重要。严格来讲这样其实也是不好的= =
所以就跟省赛的那个题一样,如果没有思路就用最朴素的算法乱搞,没准就过了。拼RP也是一件很纠结的事情。。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <string.h>
#include <set>
#include <queue>
#include <map>
#include <bitset>
#include <queue>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
const int N = 105;
int a[N][N], n, start, end;
struct point {
int x, y;
};
point d[N * N];
bool vis[N][N];
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
bool bfs(int u, int v) {
if (a[1][1] < u || a[1][1] > v)
return false;
memset(vis, 0, sizeof(vis));
vis[1][1] = true;
int f = 0, r = 1;
d[0].x = 1;
d[0].y = 1;
while (f < r) {
int p, q;
for (int i = 0; i < 4; i++) {
p = d[f].x + dx[i];
q = d[f].y + dy[i];
if (p < 1 || p > n || q < 1 || q > n)
continue;
if (!vis[p][q] && a[p][q] >= u && a[p][q] <= v) {
vis[p][q] = true;
d[r].x = p;
d[r++].y = q;
if (p == n && q == n) return true;
}
}
f++;
}
return false;
}
void solve() {
int l = 0, h = 110, mid, ans = 110;
while (l <= h) {
mid = (l + h) / 2;
bool flag = true;
for (int i = start; i <= end; i++)
if (bfs(i, min(i + mid, end))) {
h = mid - 1;
ans = min(ans, mid);
flag = false;
break;
}
if (flag) l = mid + 1;
}
cout << ans << endl;
}
int main() {
while (~scanf("%d", &n)) {
start = 10000;
end = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
scanf("%d", &a[i][j]);
start = min(start, a[i][j]);
end = max(end, a[i][j]);
}
solve();
}
return 0;
}