NYOJ 306
View Code
1 /* 2 题外话: 3 这道题看了好久开始以为是动态规划, 4 但怎么也看不出怎么做。 5 今看别人的代码发现竟如此简短! 6 而且还是 DFS 原来这是一道深搜题 7 而且还用到了 二分查找 8 思路: 9 先得到 可能的最小差值:是 first = map[n][n]-map[1][1]; 10 可能的最大差值是 last = 120(题中给的最大值) 11 取中间值 mid =(first + last)/2; 12 然后寻找 是否存在一条 最小差值是 mid 的路径 13 最在则 说明 可能最在比 mid 更小差值的路径 14 修改 last = mid; 15 若不存在 则 修改 first = mid+1 在 16 从新在(first,last)之间搜搜 17 18 在搜索时 我们假定 最小难度为 i (0<=i<=120) 19 则最大难度为 i+mid(i+mid<=120) 20 dfs(0,0,i,i+mid)朝四个方向搜 21 */ 22 23 #include<iostream> 24 #include<cstdio> 25 #include<cstring> 26 using namespace std; 27 28 const int size = 101; 29 30 int map[size][size]; 31 bool flag[size][size]; 32 const int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}}; 33 int n; 34 35 bool dfs(int x,int y,int low,int high) 36 { 37 int i; 38 if(x<1 || y<1 || x>n || y>n)return false; 39 if(map[x][y]<low || map[x][y]>high)return false; 40 if(flag[x][y])return false; 41 if(x==n && y==n)return true; 42 flag[x][y]=true; 43 for(i=0;i<4;++i) 44 if(dfs(x+dir[i][0],y+dir[i][1],low,high))return true; 45 return false; 46 } 47 48 bool slove(int mid) 49 { 50 int i; 51 for(i=0;i<=120-mid;++i) 52 { 53 memset(flag,0,sizeof(flag)); 54 if(dfs(1,1,i,i+mid))return true; 55 } 56 return false; 57 } 58 int main() 59 { 60 int i,j,first,last,mid; 61 while(EOF != scanf("%d",&n)) 62 { 63 for(i=1;i<=n;++i) 64 for(j=1;j<=n;++j) 65 scanf("%d",&map[i][j]); 66 first = map[n][n]-map[1][1]; 67 if(first<0)first=-first; 68 last = 120; 69 while(first<last) 70 { 71 mid = (first + last)/2; 72 if(slove(mid))last=mid; 73 else first=mid+1; 74 } 75 printf("%d\n",first); 76 } 77 return 0; 78 }