題目連結:http://codeforces.com/problemset/problem/358/D
題意:
有n個物品A[i]擺成一排,你要按照某一個順序將它們全部取走。
其中,取走A[i]的收益為:
(1)若A[i-1]和A[i+1]都沒被取走,則收益為a[i]
(2)若A[i-1]和A[i+1]被取走了一個,則收益為b[i]
(3)若A[i-1]和A[i+1]都被取走,則收益為c[i]
注:將A[1]的左邊和A[n]的右邊視為永遠有一個取不走的物品。
問你最大收益是多少。
題解:
表示狀態:
dp[i][0/1] = max wealth
表示A[i]比A[i-1]先取(0)或後取(1),此時取走A[1 to i-1]的最大收益。
找出答案:
ans = dp[n+1][1]
因為可以看做A[n]右邊有一個不取走的物品
所以dp[n+1][1]對應的就是將所有物品取走的最大獲益
如何轉移:
dp[i][0] = max(dp[i-1][0]+b[i-1], dp[i-1][1]+c[i-1])
dp[i][1] = max(dp[i-1][0]+a[i-1], dp[i-1][1]+b[i-1])
根據A[i-1]的左右情況,加上對應的取走A[i-1]的獲利,即為當前的總獲利。
邊界條件:
dp[1][0] = 0
dp[1][1] = -INF
因為將A[1]左邊看作有一個物體,所以只能是A[1]先選,當前總獲利為0。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_N 3005 5 #define INF 1000000000 6 7 using namespace std; 8 9 int n; 10 int a[MAX_N]; 11 int b[MAX_N]; 12 int c[MAX_N]; 13 int dp[MAX_N][2]; 14 15 void read() 16 { 17 cin>>n; 18 for(int i=1;i<=n;i++) cin>>a[i]; 19 for(int i=1;i<=n;i++) cin>>b[i]; 20 for(int i=1;i<=n;i++) cin>>c[i]; 21 } 22 23 void work() 24 { 25 dp[1][0]=0; 26 dp[1][1]=-INF; 27 for(int i=2;i<=n+1;i++) 28 { 29 dp[i][0]=max(dp[i-1][0]+b[i-1],dp[i-1][1]+c[i-1]); 30 dp[i][1]=max(dp[i-1][0]+a[i-1],dp[i-1][1]+b[i-1]); 31 } 32 cout<<dp[n+1][1]<<endl; 33 } 34 35 int main() 36 { 37 read(); 38 work(); 39 }