立志成为饮水机!

洛谷 P1434 [SHOI2002]滑雪

这道题适合记忆化练手

毕竟总有些大佬虐题。

这个题有几个剪枝

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;
}

 

posted @ 2019-06-20 20:00  寒冰大大  阅读(342)  评论(0编辑  收藏  举报