EOJ-1853 Mountain Walking
http://acm.cs.ecnu.edu.cn/problem.php?problemid=1853
题意,从图的左上角走到图的右下角,寻找一条路径使得路径上的数字的MAX-MIN最小(不在意路径的长度)
直接DFS剪枝比较难写(也感觉要T),看到差值最大为110,用二分枚举了差值(MAX-MIN)(从0到110),再枚举了图上的最小值。
大意就是,先二分枚举差值m,再枚举图中可能的最小值a(从真·最小值到真·最大值),min=a,max=a+m。
接着对起点DFS,看能否在min<mat[x][y]<max的情况下,找到一条路径。若找到则尝试找到一条差值m更小的路径,否则提高差值。
1 #include<map> 2 #include<set> 3 #include<list> 4 #include<cmath> 5 #include<ctime> 6 #include<queue> 7 #include<stack> 8 #include<cctype> 9 #include<cstdio> 10 #include<string> 11 #include<cstdlib> 12 #include<cstring> 13 #include<iostream> 14 #include<algorithm> 15 using namespace std; 16 int n; 17 int gMax,gMin; //表示图中值的最大值和最小值 18 int mat[105][105]; 19 bool v[105][105]; 20 bool path; //判断是否存在一条路径 21 void dfs(int x,int y,int Min,int Max){ 22 if(path) return ; //需满足的条件: 23 if(x<1 || x>n || y<1 || y>n) return ; //1.在图的内部 24 if(v[x][y]) return ; //2.未被访问 25 if(mat[x][y]<Min || mat[x][y]>Max) return ; //3.图上的值的范围在枚举范围之内 26 if(x==n && y==n) { path=1;return;} //找到路径 27 v[x][y]=1; 28 dfs(x+1,y,Min,Max); 29 dfs(x-1,y,Min,Max); 30 dfs(x,y+1,Min,Max); 31 dfs(x,y-1,Min,Max); 32 } 33 bool findPath(int dif){ 34 for(int i=gMin;i<gMax;i++){ //枚举图中的最小值 35 int j=i+dif; //最大值则是最小值加上枚举的差值 36 memset(v,0,sizeof(v)); 37 path=0; 38 dfs(1,1,i,j); 39 if(path) 40 return true; 41 } 42 return false; 43 } 44 int main(){ 45 while(~scanf("%d",&n)){ 46 gMax=-1;gMin=111; 47 for(int i=1;i<=n;i++) 48 for(int j=1;j<=n;j++){ 49 scanf("%d",&mat[i][j]); 50 gMax=max(gMax,mat[i][j]); //记录图中值的最大及最小 51 gMin=min(gMin,mat[i][j]); 52 } 53 int l=0,r=110; 54 while(l<r){ 55 int m=(l+r)/2; 56 if(findPath(m)) //二分枚举,若存在差值为m的道路则尝试寻找更小的 57 r=m; 58 else l=m+1; 59 } 60 printf("%d\n",r); 61 } 62 return 0; 63 }