这道题适合记忆化练手
毕竟总有些大佬虐题。
这个题有几个剪枝
1.记忆化
这个不用多说了吧
剪枝就是
如果 当前点到下面一个点的目前下降的高度+1 小于 下面那个点 能下降的高度
那么反过来,这个点不也有更大的值吗
既然这样的话,又可以得出
这个点不是最优解了,因为另外一条路线已经滑了更大的一个高度了,剩下高度相同,你觉得哪个滑的高
举例: 已知a>b 那么必然的,a+c>b+c
2.从高到低枚举起点。
可以肯定的是,目前选择的这个点的高度已经是这次dfs最大能够滑雪的高度了,如果有比这个高的答案,那么我们已经得到了而且后面不会有比这个高的答案了,所以后面的剪枝都不用做了
这个剪枝优化前的效果:
优化后:
懂了吧,上代码
#include<iostream> #include<cmath> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; int n,m; struct p{ int x,y,height; }; int a[120][120]; int dx[]={0,0,1,-1}; int dy[]={1,-1,0,0}; p s[12000]; int f[120][120]; int mmx=1; int cmp(p a,p b) { return a.height>b.height; //sort: <则为从小到大 >则为从大到小 } void dfs(int x,int y) { for(int i=0;i<=3;i++) { int nx,ny; nx=x+dx[i]; ny=y+dy[i]; if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&a[x][y]>a[nx][ny]) //判断是否越界以及能否走到那个点 { if(f[nx][ny]<f[x][y]+1) { f[nx][ny]=f[x][y]+1; mmx=max(f[nx][ny],mmx); dfs(nx,ny); } } } return ; } int main() { scanf("%d %d",&n,&m); int i,j; int tot=0; for(i=1;i<=n;i++) for(j=1;j<=m;j++) { f[i][j]=1; scanf("%d",&a[i][j]); s[++tot].height=a[i][j]; s[tot].x=i; s[tot].y=j; } sort(s+1,s+tot+1,cmp); //做一遍sort得到从高到低的位置(点) for(i=1;i<=tot;i++) { dfs(s[i].x,s[i].y); if(tot-i+1<mmx) break; } printf("%d",mmx); return 0; }