洛谷P1434滑雪講解

題源:【是兄弟就來砍我】ios

 


 

我以爲這道題主要方法應該有兩種:c++

 

下面會分別對這兩種方法進行簡述算法



 一,動態規劃法
首先的想法是用L(i,j)表示從點(i,j)出發能到達的最長距離。由於從(i,j)出發最少能滑行本身1格,因此每一個點L值都先初始化爲1數組

咱們能夠從 (i,j) 出發,向四周尋找,若是四周沒有比他低的點,那麼L(i,j)即爲1,不然L(i,j)就爲從(i,j)出發四周高度比L低且L值最大的那個點P的L值加1
遞推時的順序爲點的高度由低到高,那麼在遞推過程當中,計算L(i,j)時,他四周比他低的點P的L值必定已經被計算出來了
接下來須要解決的問題即是如何按點的高度由小到大遞推ide

關於這個問題,咱們難道要每次遞推時用兩遍循環找出當前未遞推的最低點?函數

顯然不可取,時間複雜度會爆炸的。那麼就考慮可否一個sort()解決問題懶得本身寫排序)。sort()能給一個二維數組排序?不知大佬們怎麼想,反正本蒟蒻不會。。。那爲了`sort()更香能夠方便的使用,我用一個一維數組進行存儲每一個點的數據。spa

這時候不得不說,結構體真香真的實用。下面用代碼直觀地說一下這個結構體code

1 struct Point{
2 int r; //行號
3 int c; //列號
4 int h; //高度
5 bool operator < (const Point & p) const {
6 return h < p.h;
7 }//構造函數,不懂的同窗能夠寫一個cmp代替,下面代碼會有特別說明
8 };Point point[10101];

 


爲了方便儲存以及不形成浪費我的習慣)這裏i和j都從0開始取,那麼點(i,j)用point數組存的下標爲c * i + j
 因爲i,j從0開始存,c * i + j這個式子表示的是第i+1行第j+1個數,那麼,i最大爲R-1,j最大爲C-1,整個數組最大下標爲C*(R-1)+C-1,即C*R-1
 若i,j從1開始取,爲保證運算方便及善待空間,下標應爲C*(i-1)+j-1

該算法的分析已給出,你們能夠結合代碼自行理解blog

 1 #include <iostream>//頭文件,很少解釋
 2 #include <cstdio>
 3 #include <algorithm>
 4 using namespace std;
 5 struct Point{
 6     int r;//行號
 7     int c;//列號
 8     int h;//高度
 9     bool operator < (const Point & p) const {
10         return h < p.h;//構造函數,不會的可刪掉看下面cmp
11     }
12 };Point point[10101];
13 int cmp(Point a,Point b){
14     if (a.h < b.h)   //若是a的高度小於b的高度
15       return 1;//返回真
16     else
17       return 0;//不然返回假
18 }
19 int R,C,ans = -0x3ffff;//需初始化ans爲較小值(懼怕玄學出錯)
20 int a[101][101],d[102][102];//a爲每點的高度,d爲該點可滑行的最大值
21 int main(){
22     cin >> R >> C;
23     for (int i = 0;i < R;i ++)
24       for (int j = 0;j < C;j ++){
25           cin >> a[i][j];//輸入點的高度
26           point[i * C + j].h = a[i][j];//根據上面所說的下標,
27           point[i * C + j].r = i;          //對點的數據進行存儲
28           point[i * C + j].c = j;
29           d[i][j] = 1;            //初始可滑行長度爲1
30       }
31     sort(point,point + R * C);//若是用了cmp可換爲sort(point,point + R * C,cmp);
32     for (int i = 0;i < R * C;i ++){
33         int r = point[i].r;//找一個替身,怕玄學或運算時出錯
34         int c = point[i].c;//同理
35         if (r > 0 && a[r - 1][c] < a[r][c])//找上面的
36           d[r][c] = max(d[r][c],d[r - 1][c] + 1);//進行更新
37         if (c > 0 && a[r][c - 1] < a[r][c])//找左面的
38           d[r][c] = max(d[r][c],d[r][c - 1] + 1);//進行更新
39         if (r < R - 1 && a[r + 1][c] < a[r][c])//找下面的
40           d[r][c] = max(d[r][c],d[r + 1][c] + 1);//進行更新
41         if (c < C - 1 && a[r][c + 1] < a[r][c])//找右面的
42           d[r][c] = max(d[r][c],d[r][c + 1] + 1); //進行更新
43     }
44     for (int i = 0;i < R;i ++)
45       for (int j = 0;j < C;j ++)
46         ans = max(ans,d[i][j]); //找出最大值
47     cout << ans;
48     return 0;//完美撒花
c++ Code

 

初步發佈時間:2019.11.25持續修改完善排序

相關文章
相關標籤/搜索