1. 程式人生 > >DP練習1題解B

DP練習1題解B

DP練習1題解B

先上題目描述 POJ2181

在這裡插入圖片描述

樣例輸入
8
7
2
1
8
4
3
5
6

樣例輸出

17

因為有兩個方向 如果只開一個數組dp[i],難以儲存前一步是上還是下
而考慮到只要奶牛不是傻子(其實是人不是傻子) 最後一步一定是上
那麼容易想到是不是可以用dp[i]儲存到當前最大的跳躍能量(最後一步為上)

那麼需要考慮就是下的那步 從dp[j]轉移到dp[i],下的一步應該是i到j的最小值
那就要開一個數組預處理 但看到150000我們知道只有O(n)才能救中國 肯定不行

因為之前的思路問題在無法處理下的那步狀態 那麼換個角度可以想到開兩個陣列
一個儲存當前步為下的最優子狀態,一個儲存當前步為上的最優子狀態。
我把它們命名為u[ ] d[ ]
得到狀態轉移方程:
u[i]=max(d[i-1]+a[i],u[i-1])
d[i]=max(u[i-1]+a[i],d[i-1])

眾所周知 狀態轉移方程出來 題目就做完了 因此

程式碼如下:

#include<iostream>
#include<cstring>
int u[150001];
int d[150001];
int a[150001];
using namespace std;
int main()
{
 int n,i;
 memset(a,0,sizeof(a));
 memset(d,0,sizeof(d));
 memset(u,0,sizeof(u));
 cin>>n;
 cin>>a[1];
 cin>>a[2];
 d[2]=a[1]-a[2];
 u[2]=a[1];
 if (a[2]>u[2]) u[2]=a[2];
 for (i=3;i<=n;i++)
 {
  cin>>a[i];
  u[i]=u[i-1];
  d[i]=d[i-1];
  if (d[i-1]+a[i]>u[i]) u[i]=d[i-1]+a[i];
  if (u[i-1]-a[i]>d[i]) d[i]=u[i-1]-a[i];
 }
 cout<<u[n]<<endl;
}

以上