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
题意:在给定区域内找出一列递减的序列,输出长度即可。
思路:这一题之前写过两遍,是利用dfs进行搜索记录长度。
注意:记忆化搜索的本质是遇到已经计算过的点直接返回该值即可,不需要进行标记。但是为啥返回的时候步数不用-1我也不知道。。
先上之前dfs过的代码:
1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 using namespace std; 5 6 int aa,bb; 7 int a[110][110]; 8 int ss[110][110]; 9 10 int dir[4][2]= {{1,0},{-1,0},{0,-1},{0,1}}; 11 int dfs(int x,int y) 12 { 13 if(ss[x][y]!=0) 14 return ss[x][y]; 15 for(int i=0; i<4; i++) 16 { 17 int tx=x+dir[i][0]; 18 int ty=y+dir[i][1]; 19 if(tx>=0&&tx<aa&&ty>=0&&ty<bb&&a[tx][ty]<a[x][y]) 20 { 21 int maxx=dfs(tx,ty)+1; 22 if(maxx>ss[x][y]) 23 { 24 ss[x][y]=maxx; 25 } 26 } 27 } 28 return ss[x][y]; 29 } 30 int main() 31 { 32 cin>>aa>>bb; 33 memset(a,0,sizeof(a)); 34 memset(ss,0,sizeof(ss)); 35 for(int i=0; i<aa; i++) 36 { 37 for(int j=0; j<bb; j++) 38 { 39 cin>>a[i][j]; 40 } 41 } 42 43 int ans=-1; 44 for(int i=0; i<aa; i++) 45 { 46 for(int j=0; j<bb; j++) 47 { 48 ss[i][j]=dfs(i,j); 49 ans=max(ss[i][j],ans); 50 } 51 } 52 cout<<ans+1<<endl; 53 return 0; 54 }
另外一种写法:
由于今天做题目碰到一题需要记录路径的,发现用dfs写再通过回溯好像是没法实现,所以换了一种写法写这道题,但是思路还是和dfs的差不多。
这一题记录好坐标后需要进行排序,一定要排序,不懂得话可以用
2 3
6 5 4
3 2 1这组例子来测试一下结果
必须要排序,从大到小或者从小到的都可以,控制好后面代码的比较就可以了
我的代码是从小到大排序,所以在后面实现的时候找的从当前该点出发,找四周小于该点的
因为从小到大比较,所以每个点的状态都来自于前一个比它小的点,所以从小到大排序,从大的往小的上面找,有点dp的感觉
1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<string.h> 5 using namespace std; 6 const int N=110; 7 //h减小 8 int dp[N][N]; 9 int a[N][N]; 10 int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; 11 12 13 struct node 14 { 15 int x; 16 int y; 17 int z; 18 }e[N*N]; 19 20 int cmp1(node xx,node yy) 21 { 22 return xx.z<yy.z; 23 } 24 int main() 25 { 26 int m,n; 27 scanf("%d %d",&m,&n); 28 int p=0; 29 for(int i=1;i<=m;i++) 30 { 31 for(int j=1;j<=n;j++) 32 { 33 scanf("%d",&a[i][j]);//需要存一下,否则后面没法比较 34 // scanf("%d",&kk); 35 e[p].x=i; 36 e[p].y=j; 37 e[p++].z=a[i][j]; 38 dp[i][j]=1; 39 } 40 } 41 sort(e,e+p,cmp1);//必须要排序,从大到小或者从小到的都可以,控制好后面代码的比较就可以了 42 //我的代码是从小到大排序,所以在后面实现的时候找的从当前该点出发,找四周小于该点的 43 //因为从小到大比较,所以每个点的状态都来自于前一个比它小的点,所以从小到大排序,从大的往小的上面找,有点dp的感觉 44 int pp,qq,ww; 45 int maxx=-1; 46 for(int i=0;i<p;i++) 47 { 48 // cout<<e[i].x<<" "<<e[i].y<<" "<<e[i].z<<endl; 49 pp=e[i].x; 50 qq=e[i].y; 51 ww=e[i].z; 52 for(int j=0;j<4;j++) 53 { 54 int tx=pp+dir[j][0]; 55 int ty=qq+dir[j][1]; 56 if(tx>=1&&tx<=m&&ty>=1&&ty<=n&&a[tx][ty]<ww) 57 { 58 dp[pp][qq]=max(dp[pp][qq],dp[tx][ty]+1); 59 } 60 } 61 maxx=max(maxx,dp[pp][qq]); 62 } 63 printf("%d\n",maxx); 64 return 0; 65 }