首页 > 代码库 > POJ 2110 Mountain Walking 暴力搜索+二分

POJ 2110 Mountain Walking 暴力搜索+二分

题意: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 暴力搜索+二分