Description
FJ的奶牛喜欢玩硬币游戏,所以FJ发明了一个新的硬币游戏。一开始有N(5<=N<=2,000)个硬币堆成一叠,从上往下数第i个硬币有一个整数值C_i(1<=C_i<=100,000)。
两个玩家轮流从上倒下取硬币,玩家1先取,可以从上面取1个或2个硬币,下一轮的玩家可以取的硬币数量最少为1个,最多为上一个玩家取的数量的2倍,硬币全部取完比赛结束。
已知玩家2绝顶聪明,会采用最优策略,现在请你帮助玩家1,使得玩家1取得的硬币值的和最大。
两个玩家轮流从上倒下取硬币,玩家1先取,可以从上面取1个或2个硬币,下一轮的玩家可以取的硬币数量最少为1个,最多为上一个玩家取的数量的2倍,硬币全部取完比赛结束。
已知玩家2绝顶聪明,会采用最优策略,现在请你帮助玩家1,使得玩家1取得的硬币值的和最大。
Input
第一行输入N
第二至N+1行每行输入一个整数C_i
第二至N+1行每行输入一个整数C_i
Output
输出玩家1能获得的最大值。
Solution
Fi,j,i表示的是我现在的位置(还剩多少枚硬币),取到第几个,j是对方上一次对方拿走了多少个。
下一次对手就可以取走2*j枚硬币,我们设他要拿走k枚硬币,那么k的取值范围就在1<k<=2∗j。
fi,j=max(sumi+1..k−fk,k−i(1<=k<=2∗j))
fi,j+1=max(sumi+1..k−fk,k−i(1<=k<=2*(j+1)))
J就只有在这个地方发生了改变(手指上方S)
(1<=k<=2∗j) 和 (1<=k<=2*(j+1)) 可以变为 2*j<=k<=2*(j+1)
Fi,j=max(Fi,j−1,Sumi+1..k−Fk,k−i(2∗(j−1)<k<=2∗j))
Fi,j;=max(Fi,j-1,Sumi+1..k-Fk,k-i) (2j+1<=k<=2j+2) (Sum为前缀和)
Maxn;=max(Maxn,Sum[k]-Sum[i]-F[k,k-i])
答案即为 (sum[n]+max(num[1]-f[1,1],num[1]+num[2]-f[2,2])) div 2
因为一开始可以选1或者2
复杂度;O(n2) (2算是常数)
代码
1 var 2 n:longint; 3 a,sum:array [0..2001] of longint; 4 f:array [0..2001,0..2001] of longint; 5 procedure init; 6 var 7 i:longint; 8 begin 9 readln(n); 10 sum[0]:=0; 11 for i:=1 to n do 12 begin 13 readln(a[i]); 14 sum[i]:=sum[i-1]+a[i]; 15 end; 16 end; 17 18 function min(o,p:longint):longint; 19 begin 20 if o<p then exit(o); 21 exit(p); 22 end; 23 24 function max(o,p:longint):longint; 25 begin 26 if o>p then exit(o); 27 exit(p); 28 end; 29 30 procedure main; 31 var 32 i,j,k,maxx:longint; 33 begin 34 for i:=n-1 downto 1 do 35 begin 36 maxx:=-maxlongint; 37 for j:=1 to i do 38 begin 39 for k:=min(i+2*j-2,n)+1 to min(i+2*j,n) do 40 maxx:=max(maxx,sum[k]-sum[i]-f[k,k-i]); 41 f[i,j]:=maxx; 42 end; 43 end; 44 writeln((sum[n]+max(a[1]-f[1,1],a[1]+a[2]-f[2,2])) div 2); 45 end; 46 47 begin 48 init; 49 if n=1 then writeln(a[1]) 50 else main; 51 end.