问题描述:
Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。
Input
输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
Output
输出最长区域的长度。
Sample Input
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
Sample Output
25
http://wenku.baidu.com/view/4064ef970029bd64783e2cee.html?re=view这个课件对着个问题讲的很清楚,
先贴一下解这个题目的过程 最开始为了练习dfs,即使知道肯定要超时 ,还是写了:
#include<iostream> #include<string.h> using namespace std; int R,C; int cnt[101][101]; int visited[101][101]; int Max,step; int dic[4][2]= {{0,1},{1,0},{-1,0},{0,-1}}; void dfs(int x,int y) { if(step>Max) Max=step; for(int k=0; k<4; k++) { int tx = x + dic[k][0]; int ty = y + dic[k][1]; if(tx >= 0 && tx < R && ty >= 0 && ty < C && !visited[tx][ty]&&cnt[tx][ty]<cnt[x][y]) { step++; visited[x+dic[k][0]][y+dic[k][1]]=1; dfs(x+dic[k][0],y+dic[k][1]); visited[x+dic[k][0]][y+dic[k][1]]=0; step--; } } return ; } int main() { while(cin>>R>>C) { int x,y; Max=0; memset(cnt,0,sizeof(cnt)); for(int i=0; i<R; i++) for(int j=0; j<C; j++) { cin>>cnt[i][j]; } for(x=0; x<R; x++) for(y=0; y<C; y++) { memset(visited,0,sizeof(visited)); step=1; visited[x][y]=1; dfs(x,y); visited[x][y]=0; } cout<<Max<<endl; } return 0; }
恰好的是,中午实验室看见迪神了 迅速的被他改成了bfs,结果还是超时,晚上我又把代码发给他 然后他做了下优化,减少了搜索路径 然后才过了,
他的代码:
#include <iostream> #include <string.h> #include <algorithm> #include <queue> #include <cstdio> #include <cmath> using namespace std; int R,C; int cnt[101][101]; int ret[101][101]; int vis[101][101]; int step; int dic[4][2]= {{0,1},{1,0},{-1,0},{0,-1}}; int dfs(int x, int y) { int res = 1; for(int i = 0;i < 4; ++i) { int tx = x + dic[i][0]; int ty = y + dic[i][1]; if(tx >= 0 && tx < R && ty >= 0 && ty < C && cnt[tx][ty] < cnt[x][y]) { if(vis[tx][ty]) { res = max(res, 1 + vis[tx][ty]); } else { res = max(res, 1 + dfs(tx, ty)); } } } return vis[x][y] = res; } int main() { while(cin>>R>>C) { int x = 0,y = 0; memset(cnt,0,sizeof(cnt)); for(int i=0; i<R; i++) for(int j=0; j<C; j++) { cin>>cnt[i][j]; } memset(vis, 0, sizeof(vis)); int ans = 0; for(x=0; x< R; x++) for(y=0; y < C; y++) { if(!vis[x][y]) { dfs(x, y); } } for(int i = 0;i < R; ++i) { for(int j = 0;j < C; ++j) { ans = max(ans, vis[i][j]); } } printf("%d\n", ans); } return 0; }
接下来 是我的代码:这两个代码的总体思想一样,求出求出每个点出发的最大滑行距离,并且某个点出发的最大滑行距离等于下一个可以走的点的最大滑行距离+1,遇到访问过的结点 直接就可以利用了 避免了重复搜索。
#include<iostream> #include<string.h> using namespace std; int R,C; int cnt[101][101]; int visited[101][101]; int Max,result; int dic[4][2]= {{0,1},{1,0},{-1,0},{0,-1}}; int dfs(int x,int y) { int result=1,temp; if(visited[x][y]) return visited[x][y]; for(int k=0; k<4; k++) { int tx = x + dic[k][0]; int ty = y + dic[k][1]; if(tx >= 0 && tx < R && ty >= 0 && ty < C && cnt[tx][ty] < cnt[x][y]) { result = max(result,dfs(tx,ty)); visited[x][y]=visited[x][y]<result?result+1:visited[x][y]; } } return visited[x][y]; } int main() { while(cin>>R>>C) { int x,y; for(int i=0; i<R; i++) for(int j=0; j<C; j++) { cin>>cnt[i][j]; } for(int k=0; k<R; k++) for(int d=0; d<C; d++) visited[k][d]=0; for(int i=0; i<R; i++) for(int j=0; j<C; j++) { dfs(i,j); } int ans=1; for(int i = 0; i < R; ++i) { for(int j = 0; j < C; ++j) { ans=max(ans,visited[i][j]); } } cout<<ans<<endl; } return 0; }