1. 程式人生 > 實用技巧 >洛谷P1434滑雪-題解

洛谷P1434滑雪-題解

原題:

思路:

首先考慮暴搜。

對於每一個點,我記錄到這一格為止,走過了多少路。然後列舉四個方向繼續遞迴。直到徹底走不動之後,就停下來更新答案。

但是有個問題——資料規模最大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;
}