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

 

你可能感兴趣的:(poj)