John is a fan of amusement parks. He goes every weekend and plays di erent games. This weekend he
found a challenging one | it is a target shooting game. The targets are placed along a straight line.
For all target positions i (assume the target numbering goes from right to left), there are three possible
points that John can win if he chooses that target: ai, if there are no neighbor targets chosen, bi if one
neighbor, and ci if two neighbors. Could you help John choose the targets in order to maximize the
number of points he can win?
Input
The input le contains several test cases, each of them as described below.
The program input starts with the number n (n < 1000000) of targets. Follows the values of ai, bi,
and ci for each target i.
The input data are correct and terminate with an end of le.
Output
For each test case, the program write to the output the maximum number of points John can win on
a line by itself.
The program prints the result to the standard output from the beginning of a line.
Hint: Input/output samples are in the table below. There are two tests. Each consists of only one
target.
For the rst one n = 1, a1 = 3, b1 = 0, c1 = 0, and the maximum number of points is 3. For the
second one n = 1, a1 = 1, b1 = 2, c1 = 3, and the maximum number of points is 1.The result consists
of the maximum number of points John can win, printed from the beginning of the line.
Sample Input
1
3 0 0
1
1 2 3
Sample Output
3
1
题意:n个靶子,现在要选一些靶子,使得得分最高。对于第i个靶子,如果它左右两边都没有靶子被选那么可以得到a(i)分,如果两边只有一边被选,可以得到b(i)分。如果两边的靶子都被选,得到c(i)分。
题解:开始的时候问题是:从1到n个靶子中选靶子,并且第1个的前一个靶子没有被选。
如果选了第1个靶子,那么问题变成了:从2到n的靶子中选靶子,并且第1个靶子的前一个靶子被选。
如果没有选第1个靶子,那么问题变成了:从2到n的靶子中选靶子,并且第1个靶子的前一个靶子没被选。
可以发现下面两个问题是第一个问题的子问题。
所以我们可以用dp[i][0,1]表示从i到n的靶子中选靶子,第1个靶子的前一个选或没选,能得到的最大分数。
但是转移的时候,为了计算选一个靶子的得分,我们还要记录一维状态表示第1个靶子选或者没选。
用dp[i][0,1][0,1]表示从i到n的靶子中选靶子,第1个靶子的前一个靶子选或者没选,第1个靶子选或者不选,该状态下的最大得分。
转移如下:
dp[i][0][0]=max(dp[i+1][0][0],dp[i+1][0][1]).
dp[i][1][0]=max(dp[i+1][0][0],dp[i+1][0][1]).
dp[i][0][1]=max(dp[i+1][1][0]+a[i],dp[i+1][1][1]+b[i]).
dp[i][1][1]=max(dp[i+1][1][0]+b[i],dp[i+1][1][1]+c[i]).
初始化:
dp[n][0,1][0]=0;
dp[n][0][1]=a[n];
dp[n][1][1]=b[n];
当这题还有其他的dp方法,如dp[i][j]表示前i个靶子已经处理了,第i-2,i-1,i个靶子选与没选的二进制状态为j,该状态能得到的最大分数。
代码如下:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<list>
#include<queue>
#include<string.h>
#define nn 1100000
#define inff 0x3fffffff
using namespace std;
typedef long long LL;
int a[nn],b[nn],c[nn];
LL dp[nn][2][2];
int n;
int main()
{
int i;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i],&b[i],&c[i]);
}
dp[n][0][0]=dp[n][1][0]=0;
dp[n][1][1]=b[n];
dp[n][0][1]=a[n];
for(i=n-1;i>=1;i--)
{
dp[i][0][0]=max(dp[i+1][0][0],dp[i+1][0][1]);
dp[i][1][0]=max(dp[i+1][1][0],dp[i+1][1][1]);
dp[i][0][1]=max(dp[i+1][1][0]+a[i],dp[i+1][1][1]+b[i]);
dp[i][1][1]=max(dp[i+1][1][0]+b[i],dp[i+1][1][1]+c[i]);
}
printf("%lld\n",max(dp[1][0][1],dp[1][0][0]));
}
return 0;
}