1. 程式人生 > >POJ 2110 Mountain Walking 暴力搜索+二分

POJ 2110 Mountain Walking 暴力搜索+二分

brush pac 情況 cnblogs typedef main lag highlight bool

題意:n*n的矩陣 每次能走四個方向,定義路徑的花費為:路徑中方格的max-min,問從左上到右下的最小花費,n<=100
4個方向不是DAG,不能DP,暴力搜索 每個點最壞情況下走n*n 共n*n個點 O(n^4)TLE
二分ans後 枚舉下界,則此時知道路徑的最小值和最大值從

起點出發把mn<=c<=mx的點都遍歷,此時dfs 相當於遍歷圖,不用回溯,復雜度為O(n^3*logn)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> ii;
const int N=3e2+20;

int n,ans,c[N][N],vis[N][N];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
bool dfs(int x,int y,int mn,int mx)
{ 
	
	if(c[x][y]>mx||c[x][y]<mn)
		return false;
	if(x==n&&y==n)
		return true;	
	for(int i=0;i<4;i++)
	{
		int a=x+dx[i],b=y+dy[i];
		if(a>=1&&a<=n&&b>=1&&b<=n&&!vis[a][b])
		{
			vis[a][b]=1;
			if(dfs(a,b,mn,mx))
				return true;
		}
	}
	return false;
}
void solve()
{
	int l=0,r=110,ans;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		bool flag=false;
		for(int i=0;i<=c[1][1];i++)
		{
			memset(vis,0,sizeof(vis));
			vis[1][1]=1;	
			if(dfs(1,1,i,i+mid))
			{
				flag=true;
				break;
			}
		}
		if(flag)
			ans=mid,r=mid-1;
		else
			l=mid+1;
	}
	cout<<ans<<endl;
}
int main()
{ 
	while(cin>>n)
	{
		ans=1e9;
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				scanf("%d",&c[i][j]);
			}
		}
		solve();
	}
	
	return 0;
}

  

POJ 2110 Mountain Walking 暴力搜索+二分