原题链接:http://codeforces.com/problemset/problem/1195/C
题意:给出两行数字(个数相同),每两个数字不能上下或左右相邻,计算出所有数字满足条件的最大和。
思路:利用dp数组存储到达每一个位置的最大值,方法的核心在于选或不选。根据经典的背包问题,选则总价值增加,当前容量减少,不选则保留当前数值不变。回归本题,选则当前值加另一行积累的dp数值,不选则保持本行已积累数值不变。最终两行分别得出所积累的dp数值,选较大的一个输出。总而言之,每一行对应一个数组,记录当前和的最大值。
for(int i=1;i<=n;i++){
dp[0][i]=max(a[i]+dp[1][i-1],dp[0][i-1]);
dp[1][i]=max(b[i]+dp[0][i-1],dp[1][i-1]);
}
细节:i从1开始,第一次循环用到(i-1)时i即为0,不会有乱七八糟的数据被计算;遍历某一行时,若选择选用本行的数值,相加时引用的是另一行的数据,所以不会发生因遍历而使得数值相邻的情况。
完整代码:
#include <iostream>
#include <algorithm>
using namespace std;
#define N 1000010
typedef long long ll;
ll a[N],b[N],dp[3][N];
int main(int argc, char** argv) {
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(int i=1;i<=n;i++){
scanf("%lld",&b[i]);
}
for(int i=1;i<=n;i++){
dp[0][i]=max(a[i]+dp[1][i-1],dp[0][i-1]);
dp[1][i]=max(b[i]+dp[0][i-1],dp[1][i-1]);
}
printf("%lld\n",max(dp[0][n],dp[1][n]));
return 0;
}