【二分答案+枚举】AOJ-215 Mountain Walking

来源:互联网 发布:驱动软件下载排行榜 编辑:程序博客网 时间:2024/06/03 21:37
Mountain Walking
Time Limit: 1000 ms   Case Time Limit: 1000 ms   Memory Limit: 64 MB
Judge By Case
Description
Farmer John and Bessie the cow have embarked on one of those 'active' vacations. They spend entire days walking in the mountains and then, at the end of the day, they tire and return to their vacation cabin. 

Since climbing requires a lot of energy and they are already tired, they wish to return to the cabin using a path that has the least difference between its highest and lowest elevations, no matter how long that path is. Help FJ find this easy-to-traverse path. 

The map of the mountains is given by an N x N (2 <= N <= 100) matrix of integer elevations (0 <= any elevation <= 110) FJ and Bessie are currently at the upper left position (row 1, column 1) and the cabin is at the lower right (row N, column N). They can travel right, left, toward the top, or toward the bottom of the grid. They can not travel on a diagonal.

Input
* Line 1: The single integer, N 

* Lines 2..N+1: Each line contains N integers, each of which specifies a square's height. Line 2 contains the first (top) row of the grid; line 3 contains the second row, and so on. The first number on the line corresponds to the first (left) column of the grid, and so on. 

Output
* Line 1: An integer that is the minimal height difference on the optimal path.

Sample Input
OriginalTransformed
51 1 3 6 81 2 2 5 54 4 0 3 38 0 2 3 44 3 0 2 1

Sample Output
OriginalTransformed
2

————————————————————国庆的分割线————————————————————

前言:Roll神带我找水题……

思路:该题是锻炼二分答案思想的。听了Roll神的指导受益匪浅——

通过二分答案可以得到一个未知量,然后通过这个未知量确定已知量。

一开始我只是二分答案,然后栽在“最大值减去最小值”这句话上面了。思路太死板。dfs的时候,发现:

对于一条不确定最大值、最小值分别是几,而且也不知道能不能走到终点的路径。是没有办法进行dfs的。

因为走了不同的路径,“最大值减去最小值”这个量就是不确定的,一直在变。那么对答案的二分就没有丝毫意义。

本来是想确定一个未知量,闹了半天还是变量。这个答案对于dfs来说没有作用。


所以通过二分答案确定了“最大值减去最小值”这个量之后,根据这个已知量进行可行性判断。

如何判断呢?现在有了“差值”这个已知量,仍然不足以dfs判断。因为最大值、最小值还是不确定量。那就直接枚举最小值、最大值自然可以通过二分的答案确定下来~这样二分答案就有意义了。剩下的就是flood_fiil(dfs)了。

代码如下:

/*ID: j.sure.1PROG:LANG: C++*//****************************************/#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <stack>#include <queue>#include <vector>#include <map>#include <string>#include <climits>#include <iostream>#define LL long longusing namespace std;const int INF = 0x3f3f3f3f;/****************************************/#define LIM (nx >= 1 && nx <= n && ny >= 1 && ny <= n)const int N = 105;const int dir[][2] = {-1, 0, 0, 1, 1, 0, 0, -1};bool vis[N][N];int mat[N][N], n, s, t;void flood_fill(int x, int y){vis[x][y] = 1;for(int d = 0; d < 4; d++) {int nx = x + dir[d][0], ny = y + dir[d][1];if(!LIM || vis[nx][ny]) continue;if(mat[nx][ny] >= s && mat[nx][ny] <= t) {flood_fill(nx, ny);}}}bool check(int D){for(s = 0; s <= 110; s++) {memset(vis, 0, sizeof(vis));t = s + D;if(mat[1][1] >= s && mat[1][1] <= t && mat[n][n] >= s && mat[n][n] <= t)flood_fill(1, 1);if(vis[n][n]) return true;}return false;} int main(){#ifdef J_Sure//  freopen("000.in", "r", stdin);//  freopen(".out", "w", stdout);#endif    scanf("%d", &n);    for(int i = 1; i <= n; i++) {        for(int j = 1; j <= n; j++) {            scanf("%d", &mat[i][j]);        }    }int l = 0, r = 110;    while(l < r) {int mid = (l+r)>>1;        if(check(mid)) {            r = mid;        }else l = mid + 1;    }    printf("%d\n", r);    return 0;}


0 0