洛谷P1434滑雪-題解
阿新 • • 發佈:2020-08-07
原題:
思路:
首先考慮暴搜。
對於每一個點,我記錄到這一格為止,走過了多少路。然後列舉四個方向繼續遞迴。直到徹底走不動之後,就停下來更新答案。
但是有個問題——資料規模最大100行100列,如果我以一次遞迴4個方向來計算,第一層4種,第二層16種,第三層64種,第四層256種,而假設我們從整個地圖的中間開始找,至少要花50步找到邊界,而此時共有450種方案,這個數是1,267,650,600,228,229,401,496,703,205,376
這個數肯定爆炸
所以我們想到那些我們常用的優化。
第一,剪枝。
對於每一個到達的點,我們開一個數組記憶到這個點的最長步數。
如果最長步數大於這次到達這個點時的步數,我們可以不繼續。
第二,記憶化搜尋。
仍然記憶最長步數,如果這個點之前走過直接返回這個值。
對於每一個點的記憶值,我們選四個方向的返回值中最大的那個+1
由這個,我們想到了DP。
DP思路與上述記憶化搜尋差不多廢話記憶化搜尋就是DP,詳見下附程式碼
程式碼:
DP:
#include<bits/stdc++.h> using namespace std; int n,m,maxn; int mp[105][105]; int f[105][105]; struct node { int x; int y; int w; }N[10005]; int cnt; bool cmp(struct node a,struct node b) { return a.w<b.w; } int main() { cin >> n >> m; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { cnt++; cin >> mp[i][j]; N[cnt].x=i; N[cnt].y=j; N[cnt].w=mp[i][j]; f[i][j]=1; } sort(N+1,N+1+cnt,cmp); for(int i=1;i<=cnt;i++) { int x=N[i].x; int y=N[i].y; int w=N[i].w; if(w>mp[x-1][y]) f[x][y]=max(f[x][y],f[x-1][y]+1); if(w>mp[x][y-1]) f[x][y]=max(f[x][y],f[x][y-1]+1); if(w>mp[x+1][y]) f[x][y]=max(f[x][y],f[x+1][y]+1); if(w>mp[x][y+1]) f[x][y]=max(f[x][y],f[x][y+1]+1); if(maxn<f[x][y]) maxn=f[x][y]; } cout << maxn << endl; return 0; }