1783: [Usaco2010 Jan]Taking Turns
Description
Farmer John has invented a new way of feeding his cows. He lays out N (1 <= N <= 700,000) hay bales conveniently numbered 1..N in a long line in the barn. Hay bale i has weight W_i (1 <= W_i <= 2,000,000,000). A sequence of six weights might look something like: 17 5 9 10 3 8 A pair of cows named Bessie and Dessie walks down this line after examining all the haybales to learn their weights. Bessie is the first chooser. They take turns picking haybales to eat as they walk (once a haybale is skipped, they cannot return to it). For instance, if cows Bessie and Dessie go down the line, a possible scenario is: * Bessie picks the weight 17 haybale * Dessie skips the weight 5 haybale and picks the weight 9 haybale * Bessie picks the weight 10 haybale * Dessie skips the weight 3 haybale and picks the weight 8 haybale Diagrammatically: Bessie | | 17 5 9 10 3 8 Dessie | | This scenario only shows a single skipped bale; either cow can skip as many as she pleases when it‘s her turn.Each cow wishes to maximize the total weight of hay she herself consumes (and each knows that the other cow has this goal).Furthermore, a cow will choose to eat the first bale of hay thatmaximimizes her total weight consumed. Given a sequence of hay weights, determine the amount of hay that a pair of cows will eat as they go down the line of hay. 一排数,两个人轮流取数,保证取的位置递增,每个人要使自己取的数的和尽量大,求两个人都在最优策略下取的和各是多少。
Input
* Line 1: A single integer: N * Lines 2..N+1: Line i+1 contains a single integer: W_i
Output
* Line 1: Two space-separated integers, the total weight of hay consumed by Bessie and Dessie respectively
Sample Input
6
17
5
9
10
3
8
Sample Output
27 17
题解:
又是博弈问题。。又是DP。。。
我们是不知道第一个人从哪个开始选,但是肯定在最后一个结束。
所以我们定义f[0][i]表示先手从i到n的最大值,f[1][i]为后手。
显然f[0][i]=f[0][i+1],f[1][i]=f[1][i+1]
对于f[0][i],还有一种情况是选i,那么值为a[i]+f[1][i+1](仔细想想吧)
当然,如果选i,f[1][i]就为f[0][i+1]了
#include<stdio.h> #include<iostream> using namespace std; const int N=700005; int n,i,a[N]; long long f[2][N]; int main() { scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=n;i>=1;i--) { f[0][i]=f[0][i+1]; f[1][i]=f[1][i+1]; if(f[1][i+1]+a[i]>=f[0][i])//注意一下等于 { f[0][i]=f[1][i+1]+a[i]; f[1][i]=f[0][i+1]; } } cout<<f[0][1]<<‘ ‘<<f[1][1]; return 0; }
优化版:
#include<stdio.h> #include<iostream> using namespace std; const int N=700005; int n,i,a[N]; long long t,x,y; int main() { scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=n;i>=1;i--) if(y+a[i]>=x) { t=x; x=y+a[i]; y=t; } cout<<x<<‘ ‘<<y; return 0; }