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

 

posted @ 2011-10-11 21:06  like@neu  阅读(251)  评论(0编辑  收藏  举报