POJ 2922 Honeymoon Hike (dfs+二分答案+区间枚举)
题意:给定一个n*n地图和高度,一个人从左上角地图开始,需要走到右下角的地图,问他走的路程中所到达的最大高度和最小高度的差最小是多少。
思路:二分答案,对于每一个高度差,可以用dfs或bfs检验是否能够到达目的地,如果对每个高度差,用dfs,每次传以前的最大和最小高度,然后在更新,这样检验会超时,于是可以改用枚举高度区间的办法来缩减时间(想了半天没想出来....)。总的来所,一个不错的搜索题目。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
#include <bitset>
#include <queue>
#include <vector>
using namespace std;
const int BORDER = (1<<20)-1;
const int MAXSIZE = 37;
const int MAXN = 105;
const int INF = 1000000000;
#define CLR(x,y) memset(x,y,sizeof(x))
#define ADD(x) x=((x+1)&BORDER)
#define IN(x) scanf("%d",&x)
#define OUT(x) printf("%d\n",x)
#define MIN(m,v) (m)<(v)?(m):(v)
#define MAX(m,v) (m)>(v)?(m):(v)
#define ABS(x) ((x)>0?(x):-(x))
#define SET_NODE(no,a,b) {no.x=a;no.y=b;}
typedef struct{
int x,y;
}Node;
Node t_node;
int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
int n,tt,ans,limit,low,high;
int map[MAXN][MAXN];
bool visit[MAXN][MAXN];
bool _is(const int& x,const int& y)
{
if(x<0 || x>=n)
return false;
if(y<0 || y>=n)
return false;
return true;
}
int init()
{
CLR(visit,0);
return 0;
}
int input()
{
IN(n);
for(int i = 0; i < n; ++i)
for(int j = 0; j < n; ++j)
IN(map[i][j]);
return 0;
}
/*
bool bfs(const int& limit)
{
int x,y,i,j,tmp,high,low;
queue<Node> que;
Node node;
CLR(visit,0);
// initialize the queue
while(!que.empty())
que.pop();
visit[0][0] = true;
SET_NODE(t_node,0,0);
que.push(t_node);
low = high = map[0][0];
// while loop
cout<<limit<<endl;
while(!que.empty())
{
node = que.front();
que.pop();
if(node.x == n-1 && node.y == n-1)
return true;
for(i = 0; i < 4; ++i)
{
x = node.x + dir[i][0];
y = node.y + dir[i][1];
if(_is(x,y) && !visit[x][y])
{
t_node.low = MIN(low,map[x][y]);
t_node.high = MAX(high,map[x][y]);
if(high - low > limit)
continue;
SET_NODE(t_node,x,y);
visit[x][y] = true;
que.push(t_node);
}
}
}
return false;
}
*/
bool dfs(const int& x,const int& y)
{
int a,b,h,l;
if(map[x][y] > high || map[x][y] < low)
return false;
if(x == n-1 && y == n-1)
return true;
visit[x][y] = true;
for(int i = 0; i < 4; ++i)
{
a = x + dir[i][0];
b = y + dir[i][1];
if(!visit[a][b] && _is(a,b))
if(dfs(a,b))
return true;
}
return false;
}
int work()
{
int b_high,b_low,b_mid;
int i,j,tmp;
b_high = -1;
b_low = INF;
for(i = 0; i < n; ++i)
for(j = 0; j < n; ++j)
{
b_high = MAX(b_high,map[i][j]);
b_low = MIN(b_low,map[i][j]);
}
b_high -= b_low;
b_low = 0;
while(b_low <= b_high)
{
b_mid = (b_low+b_high)>>1;
for(low = (map[0][0]-b_mid)>0?(map[0][0]-b_mid):0;
low <= map[0][0]; ++low)
{
CLR(visit,0);
high = low + b_mid;
if(dfs(0,0))
{
ans = b_mid;
break;
}
}
if(low <= map[0][0])
b_high = b_mid - 1;
else
b_low = b_mid + 1;
}
printf("Scenario #%d:\n",tt);
OUT(ans);
printf("\n");
tt++;
return 0;
}
int main()
{
int t;
tt = 1;
IN(t);
while(t--)
{
init();
input();
work();
}
return 0;
}