P1434 [SHOI2002] 滑雪 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题数据很水,可以用记忆化过,这里说一下堆优化+DP的方法
首先是常用的DP逆向思维,也是此题最终的思路:倒着来
题目说是从从高到低:对于(i,j) 到它的四个方向的块,应该是DP[i][j]到了DP[ i+dx[] ] [ j+dy[] ],但显然这不好,我们从一个状态转为四个状态,这很不方便
但是我们如果逆向思维,从低到高走,题意是等价的,这是就从DP[ i+dx[] ] [ j+dy[] ]到 DP[i][j],四个状态转为一个状态,就舒服多了
我们令DP[i][j]为走到这个(i,j)的最多步骤
显然DP[i][j]初始值为 1 ,这步没了就WA50分
因为这个是有方向的,我们就不能傻傻的for枚举DP,这也一定不是最优值
从贪心的角度考虑,既然是从低到高走,那么每次我们从当前的最低(i,j)开始,来算出DP[i][j]的值,DP[i][j]就是从它的四个方向转移过来,这时就体现了倒这来的好处
如何每次稳定的拿到最低呢?这是就用堆来维护就可以了。自定义堆,存入下标,高度,让高度进行排序,使得堆顶是最小的高度。
#include<bits/stdc++.h> using namespace std; #define ll long long #define mp make_pair #define pb push_back //vector函数 #define popb pop_back //vector函数 #define fi first #define se second const int N=200; //const int M=; //const int inf=0x3f3f3f3f; //一般为int赋最大值,不用于memset中 //const ll INF=0x3ffffffffffff; //一般为ll赋最大值,不用于memset中 int T,n,m,h[N][N],dp[N][N]; int dx[5]={0,0,1,-1}; int dy[5]={1,-1,0,0}; struct node { int x,y,h; friend bool operator <(const node &a,const node &b) { return a.h>b.h; } }; priority_queue<node> q; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int main() { // freopen("","r",stdin); // freopen("","w",stdout); n=read(),m=read(); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { dp[i][j]=1; //这个很重要,没这个就WA了 h[i][j]=read(); q.push(node{i,j,h[i][j]}); } } int ans=0; while(!q.empty()) { node x=q.top(); q.pop(); for(int i=0;i<4;i++) { int tx=dx[i]+x.x,ty=dy[i]+x.y; if(h[tx][ty]<h[x.x][x.y]) dp[x.x][x.y]=max(dp[x.x][x.y],dp[tx][ty]+1); } ans=max(ans,dp[x.x][x.y]); } printf("%d\n",ans); return 0; }
标签:ch,洛谷,int,ll,P1434,const,SHOI2002,DP,define From: https://www.cnblogs.com/Willette/p/17065593.html