Codeforces 358D Dima and Hares:dp【只考虑相邻元素】
题目链接: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 }