題目傳送門
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
乙個人可以從某個點滑向上下左右相鄰四個點之一,當且僅當高度會減小。在上面的例子中,一條可行的滑坡為 2424-1717-1616-11(從 2424 開始,在 11 結束)。當然 2525-2424-2323-\ldots…-33-22-11 更長。事實上,這是最長的一條。
輸入的第一行為表示區域的二維陣列的行數 rr 和列數 cc。下面是 rr 行,每行有 cc 個數,代表高度(兩個數字之間用 11 個空格間隔)。
輸出區域中最長滑坡的長度。
輸入 #1複製
輸出 #1複製
對於 100%100% 的資料,1\leq r,c\leq 1001≤r,c≤100。
作為一道記憶化搜尋的題,我硬是拿dp做的。
作為本蒟蒻恢復訓練後的第一道題
一開始想的很簡單,非常容易得知狀態是\(dp[i][j]\)表示到達\((i,j)\)點的最長滑雪路徑,最後從頭到尾統計一遍最大的\(dp[i][j]\)就是答案了。
然後開始轉移,就是如果\((i,j)\)周圍的四個點比這個點高(因為只有高的能往低處滑),就更新\(dp[i][j]\)取最大就可以。
然後掛。
百思不得其解(果然半年停訓停傻了)我覺得思路比較完美,因為是一道黃題,覺得思維強度也就應該是這水平(逃)
後來發現,我直接掃瞄的轉移不是最優的。就是因為轉移的時候還沒有計算的那部分有可能更優,然而還沒來得及被計算。
就像這樣:(顯示的是dp陣列)
2 5 3 6 9 8
2 6 6 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
當前轉移到第二行第四列,但是只能從上、左兩個狀態轉移得到,事實上右、下的狀態有可能更優。所以導致答案統計不全。
那麼怎麼辦呢?
這就涉及到了dp順序的問題。以我看來,dp順序需要滿足兩種條件:第一種,轉移最優,第二種,無後效性。
我們分析問題容易得出,如果先統計低的,後統計高的,那麼就不會有轉移上的問題。在當前點,只有比它低的能轉移到它。
所以把矩陣所有的值進行排序,然後用結構體構建對映。最後按照這個順序來轉移就可以。整個過程可以用優先佇列實現。
**:
#include#include#include#includeusing namespace std;
const int maxn=110;
int n,m,ans;
int map[maxn][maxn];
int dp[maxn][maxn];//dp[i][j]表示(i,j)點的最長路
struct node
a[10010];
int tot;
struct cmp
int main()
while(!q.empty())
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans=max(ans,dp[i][j]);
printf("%d",ans);
return 0;
}
洛谷 P1434 SHOI2002 滑雪
michael 喜歡滑雪。這並不奇怪,因為滑雪的確很刺激。可是為了獲得速度,滑的區域必須向下傾斜,而且當你滑到坡底,你不得不再次走上坡或者等待公升降機來載你。michael 想知道在乙個區域中最長的滑坡。區域由乙個二維陣列給出。陣列的每個數字代表點的高度。下面是乙個例子 1 2 3 4 5 16 1...
洛谷P1434 SHOI2002 滑雪
michael喜歡滑雪。這並不奇怪,因為滑雪的確很刺激。可是為了獲得速度,滑的區域必須向下傾斜,而且當你滑到坡底,你不得不再次走上坡或者等待公升降機來載你。michael想知道在乙個區域中最長的滑坡。區域由乙個二維陣列給出。陣列的每個數字代表點的高度。下面是乙個例子 1 2 3 4 5 16 17 ...
洛谷 P1434 SHOI2002 滑雪
michael 喜歡滑雪。這並不奇怪,因為滑雪的確很刺激。可是為了獲得速度,滑的區域必須向下傾斜,而且當你滑到坡底,你不得不再次走上坡或者等待公升降機來載你。michael 想知道在乙個區域中最長的滑坡。區域由乙個二維陣列給出。陣列的每個數字代表點的高度。下面是乙個例子 1 2 3 4 5 16 1...