BZOJ 1783 [Usaco2010 Jan]Taking Turns

Description

Farmer John has invented a new way of feeding his cows. He lays outN (1 <= N <= 700,000) hay bales conveniently numbered 1..N in along 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 afterexamining all the haybales to learn their weights. Bessie is thefirst 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 haybaleDiagrammatically:Bessie | | 17 5 9 10 3 8 Dessie | |This scenario only shows a single skipped bale; either cow can skipas 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 thata 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,其实就是DP;[7*10^5哪里看起来像DP了。。。]

[填坑:因为这题是二者的博弈,具有明显的后效性,贪心基本被否定,图论向的想法也不明显,故尝试DP]

f[1,i]代表先手从n取到i的最大和。 

f[2,i]代表后手从n取到i的最大和。

对于f[1,i],f[1,i]=max(f[1,i+1],f[2,i+1]+a[i]);

f[1,i]=f[1,i+1]就意味着不取x[i],而f[1,i]=f[2,i+1]+x[i]就意味着让后手先取x[i]再把先手和后手调换。

对于f[2,i],f[2,i]=f[2,i+1],但是如果f[1,i]=f[2,i+1]+x[i],那么f[2,i]=f[1,i];

代码如下:

var
reach,n,i:longint;
f:array[1..2,0..1000000]of int64;
x:array[0..1000000]of int64;
begin
  readln(n);
  for i:=1 to n do readln(x[i]);
  reach:=n;
  for i:=n downto 1 do
  begin
    f[1,i]:=f[1,i+1];
    f[2,i]:=f[2,i+1];
    if f[1,i]<=f[2,i+1]+x[i] then
    begin
      f[1,i]:=f[2,i+1]+x[i];
      f[2,i]:=f[1,i+1];
    end;
  end;
  writeln(f[1,1],' ',f[2,1]);
end.
我们可以发现f[1,i]和f[2,i]只与f[1,i+1]和f[2,i+1]有关

所以程序可以小小地优化一下

代码如下:

var
x:array[1..700000] of longint;
i,n:longint;
a,b,t:int64;
begin
  readln(n);
  for i:=1 to n do
    readln(x[i]);
  for i:=n downto 1 do
    if b+x[i]>=a then
      begin
        t:=a;a:=b+x[i];b:=t;
      end;
  writeln(a,' ',b);
end.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值