POJ1088滑雪問題 簡單dp(動態規划)已AC


滑雪
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 99422   Accepted: 37756

Description

Michael喜歡滑雪百這並不奇怪, 因為滑雪的確很刺激。可是為了獲得速度,滑的區域必須向下傾斜,而且當你滑到坡底,你不得不再次走上坡或者等待升降機來載你。Michael想知道載一個區域中最長底滑坡。區域由一個二維數組給出。數組的每個數字代表點的高度。下面是一個例子 
 1  2  3  4 5

16 17 18 19 6

15 24 25 20 7

14 23 22 21 8

13 12 11 10 9

一個人可以從某個點滑向上下左右相鄰四個點之一,當且僅當高度減小。在上面的例子中,一條可滑行的滑坡為24-17-16-1。當然25-24-23-...-3-2-1更長。事實上,這是最長的一條。

Input

輸入的第一行表示區域的行數R和列數C(1 <= R,C <= 100)。下面是R行,每行有C個整數,代表高度h,0<=h<=10000。

Output

輸出最長區域的長度。

Sample Input

5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

Sample Output

25
 
第一次做:直接輸出長乘寬.....沒有考慮到人家不一定按回旋型輸入。只好刪掉T.T
第二次做:找到最高的那個滑坡,從它開始上下左右尋找最接近它高度的滑坡,以此類推,直到到最低。。。WA???然后默默想了十分鍾,
Oh!oh!oh!最高的滑坡不一定只有一個!!!一大堆代碼,刪掉。T.T
第三次做:終於明白了題目深意,dp(動態規划),比如25這個滑坡,要依次考慮24,20,18,22滑坡到底端的最長路徑,而例如24,又要依次考慮15,17,23
到底端的最長路徑……以此類推最后找到1到底端的最長路徑。
(str=store儲存)(ski=滑雪=滑坡)(博主不知道滑坡英語是啥....)
我們用一個str[101][101]數組存儲對應ski[101][101]中對應滑坡各自的最優解,這樣我們就沒必要每次算一個滑坡的最優解都要
不斷遞歸直到底端,然后依次求出最優解,最后再得到此滑坡的最優解,這個過程會重復許多次,所以我們只需將已經算出最優解滑坡記下來,下次
到這個滑坡時直接讀取就好,可以省下一大筆時間(如果一直遞歸會超時的)
 
 
何為動態規划:(博主表達能力不好,就上網搜了易懂的解釋)
動態規划算法的基本思想是:將待求解的問題分解成若干個相互聯系的子問題,先求解子問題,然后從這些子問題的解得到原問題的解;對於重復出現的子問題,只在第一次遇到的時候對它進行求解,並把答案保存起來,讓以后再次遇到時直接引用答案,不必重新求解。動態規划算法將問題的解決方案視為一系列決策的結果,與貪婪算法不同的是,在貪婪算法中,每采用一次貪婪准則,便做出一個不可撤回的決策;而在動態規划算法中,還要考察每個最優決策序列中是否包含一個最優決策子序列,即問題是否具有最優子結構性質。
測試數據:

3 4

10 9 8 

2 3 3

10 8 1

5 4 3

4


3 3

6 6 6

6 6 6

6 6 6

1


4 4

1 2 2 1

1 3 3 1

1 4 4 1

1 2 2 1

4


1 5

1 2 4 3 4

3


6 6

8888 9999 8888 7777 7778 7776

8887 9000 10000 7000 7900 10000

8889 9001 9889 9988 7199 10000

4444 5555 6666 7777 7776 8989

3399 5555 4444 8739 9024 3843

10000 9999 9999 2222 1111 4748

7


#include <iostream>
#include <algorithm>
using namespace std;
int r,c;//r是行,c是列
int ski[101][101];//滑坡高度
int str[101][101];//存儲每個滑坡到地面的最長路徑
int dp(int row,int col);//row=行,col=列,搜索每個滑坡的最優解
int main()
{
memset(str,0,sizeof(str));
cin>>r>>c;
for(int i=0;i<r;i++)
for(int j=0;j<c;j++)
cin>>ski[i][j];
for(int i=0;i<r;i++)
for(int j=0;j<c;j++)
str[i][j]=dp(i,j);
int max_ski=str[0][0];
for(int i=0;i<r;i++)//找出所有滑坡中的最優解
for(int j=0;j<c;j++){
if(str[i][j]>max_ski)
max_ski=str[i][j];
}
cout<<max_ski<<endl;
return 0;
}
int dp(int row,int col)
{
if(str[row][col])return str[row][col];//如果已經有最優解就直接返回
else{
//這里的max是為了取當前row,col情況下最優解
if(row-1>=0&&ski[row-1][col]<ski[row][col])//上
str[row][col]=max(str[row][col],1+dp(row-1,col));//尋找上面滑坡的最優解
if(row+1<r&&ski[row+1][col]<ski[row][col])//下
str[row][col]=max(str[row][col],1+dp(row+1,col));
if(col-1>=0&&ski[row][col-1]<ski[row][col])//左
str[row][col]=max(str[row][col],1+dp(row,col-1));
if(col+1<c&&ski[row][col+1]<ski[row][col])//右
str[row][col]=max(str[row][col],1+dp(row,col+1));
return str[row][col]?str[row][col]:1;//如果不等於0說明有比它小的滑坡,如果等於0說明,其余滑坡都大等於它
}
}


 
 

                        
                        
                 

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com