POJ/PKU 2110
最近好忙,好久没有更新- -水题做太多了。。。。。
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; }