POJ 2922 Honeymoon Hike (dfs/bfs+ dichotomy + enumeration interval)
http://poj.org/problem?id=2922
Test Instructions:
Give you a n*n grid and give the altitude of each point in the grid, and now you need to find a way from the upper left to the lower right corner, and this road at all points, the highest altitude-the lowest elevation difference is the smallest. The minimum value is output.
Analysis:
(The subject can also be implemented with BFS)
The difference between the two points of elevation. See if the elevation difference is x, if there is a path from the lower left to the upper-right corner.
This problem will time out if it is implemented with a regular DFS. because we need to record the elevation of all points encountered on the current DFS path , such as the following matrix:
A b C
D E F
G h I
We start with a, let's say we go down to D, and then go to E to find out. We marked the a,d,e at this time. Now we're going to change the initial direction from a to B to E, because even if we were to go through a D e, it doesn't mean that we're not going to have a B E. (maybe a b E is possible, you can judge it by example:
5 5
0 5
5 5)
So the regular Dfs method needs to lock the VIS and need to unlock it when exiting the DFS for that point. Similar to topological sorting.
The general DFS Timeout code is as follows:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std;
const int maxn=100+5;
int n;
int MAP[MAXN][MAXN];
int vis[maxn][maxn];//is passed int max_v,min_v when judging the current node; int dr[]={-1,1,0,0};//up or down int dc[]={0,0,-1,1}; bool Dfs (int r,int c,int d) {if (r==n&&c==n) return true;//arrival
End vis[r][c]=1;//lock, indicating that the for (int dir=0;dir<4;dir++) {int nr=r+dr[dir],nc=c+dc[dir] is being searched;
if (NR>=1&&NR<=N&&NC>=1&&NC<=N&&!VIS[NR][NC])//We only guarantee that the current does not go backwards { if (ABS (MAP[NR][NC]-MIN_V) <=d && abs (MAP[NR][NC]-MAX_V) <=d) {min_v=min (Min_v
, MAP[NR][NC]);
Max_v=min (MAX_V,MAP[NR][NC]);
if (Dfs (NR,NC,D)) return true;
}}} vis[r][c]=0;//is unlocked, indicating that the search has ended and that you can enter it as long as it is a vis==0 point.
return false;
} bool Check (int d) {max_v=min_v=map[1][1];
memset (vis,0,sizeof (VIS));
Return Dfs (1,1,D); } int Main ()
{int T; scanf ("%d", &t);
for (int kase=1;kase<=t;kase++) {scanf ("%d", &n);
for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf ("%d", &map[i][j]);
int l=0,r=200;
while (r>l) {int mid= (r+l) >>1;
if (check (mid)) R=mid;
else l=mid+1;
} printf ("Scenario #%d:\n%d", kase,r);
} return 0;
}
Now we use the Dfs method of the enumeration interval, we enumerate the possible maximum heights up and the minimum height low (their difference is D) on the path.
Also for the following matrices:
A b C
D E F
G h I
Assuming that this round enumeration is up=5,low=0, if we go before a D e does not pass, then we go after a B E is also not possible. E must have crossed the border. So here we have the VIS array as long as we walk through a point on the mark, without locking unlocked. As long as the previous point is not feasible, no matter where to walk from the point is not possible.
AC Code:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std;
const int maxn=100+5;
int n;
int MAP[MAXN][MAXN];
int vis[maxn][maxn];//is passed int max_v,min_v when judging the current node; int dr[]={-1,1,0,0};//up or down int dc[]={0,0,-1,1}; bool Dfs (int r,int c,int low,int up) {vis[r][c]=1;
Error, before the VIS is placed below if the IF (Map[r][c]>up | | | map[r][c]<low) return FALSE; if (r==n&&c==n) return true;
Reach the end point for (int dir=0;dir<4;dir++) {int nr=r+dr[dir],nc=c+dc[dir]; if (NR>=1&&NR<=N&&NC>=1&&NC<=N&&!VIS[NR][NC]) if (DFS (NR,NC,LOW,UP)) return true;
Error, here forgot to return true} return false; } bool Check (int d) {for (int low=0;low+d<=200;low++) {memset (vis,0,sizeof (VIS));
Error, where memset is placed on the for above if (DFS (1,1,LOW,LOW+D)) return true;
} return false; } int main () {int T; scanf ("%d", &Amp
T);
for (int kase=1;kase<=t;kase++) {scanf ("%d", &n);
for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf ("%d", &map[i][j]);
int l=0,r=200;
while (r>l) {int mid= (r+l) >>1;
if (check (mid)) R=mid;
else l=mid+1;
} printf ("Scenario #%d:\n%d\n\n", kase,r);
} return 0;
}