POJ2110 Moutain Walking(BFS+二分答案)
阿新 • • 發佈:2018-12-16
【題目分析】
要讓路徑上最大最小差最小(繞口令~),很明顯,二分答案即可。
關鍵在於check函式怎麼寫:首先我們確定上下界,但如果我們去二分差值,好像沒有辦法在短時間內檢驗,所以我們去二分這個上界,列舉下界,再帶入圖中檢驗。
我們發現最大的高度也不會超過110,所以我們可以列舉,而且不會爆。
路徑搜尋與普通的一樣,我採用了bfs,走之前要判斷一下map[1][1]是否在上下界內(!!!就是這個讓我調了很久)走的時候需判斷一下下一步走到的是否在上下界內。走到終點則返回true,否則返回false。
【程式碼~】
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int MAXN=105; int n; int ma[MAXN][MAXN],vis[MAXN][MAXN]; int dx[4]={1,0,-1,0}; int dy[4]={0,1,0,-1}; bool bfs(int l,int r) { if(ma[1][1]<l||ma[1][1]>r) return false; queue<pair<int,int> > q; q.push(make_pair(1,1)); vis[1][1]=1; while(!q.empty()) { int x=q.front().first,y=q.front().second; q.pop(); for(int i=0;i<4;++i) { int nx=x+dx[i],ny=y+dy[i]; if(!vis[nx][ny]&&nx>0&&nx<=n&&ny>0&&ny<=n) { vis[nx][ny]=1; if(ma[nx][ny]>=l&&ma[nx][ny]<=r) { q.push(make_pair(nx,ny)); if(nx==n&&ny==n) return true; } } } } return false; } bool check(int mid) { for(int i=0;i+mid<=110;++i) { memset(vis,0,sizeof(vis)); if(bfs(i,i+mid)) return true; } return false; } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) scanf("%d",&ma[i][j]); int l=0,r=110; while(l<r) { int mid=l+r>>1; if(check(mid)) r=mid; else l=mid+1; } cout<<r; return 0; }