题目大意:
求在一个序列里(1<n<=100),两个人从序列的两端取数,第一个人最优策略的最优得分是多少(需保证第二个人也得是最优策略)
样例输入:
6
4 7 2 9 5 2
样例输出:
18 11
解释:
两人依次选的是:2,4,7,5,9,2
第一个人=2+7+9=18
第二个人=4+5+2=11
这道题实质上是一道动态规划类题目,因为两人所选的策略都是最优策略,并不是一个贪心策略。所以,我们可以想到把一个序列来分段,也就是当前两人分别在取的序列的开头和结尾来做一个分段——也就是设f[i,j]表示i~j这个区间里先手可以获得的最优值。
状态转移方程:
f[i,j]=sum[i,j]-min(f[i-1,j],f[i,j-1]);
sum[i,j]表示i~j这个区间里的总和;
f[i-1,j]表示先手取左边而后手可获得的最优值;
f[i,j-1]表示先手取右边而后手可获得的最优值;
f[i-1,j],f[i,j-1]两者之间的最小值就是当前先手应该取的位置。
边界:
f[i,i]=a[i](1<=i<=n)
代码:
var f,sum:array[0..100,0..100]of longint; n,i,j:longint; a:array[1..100]of longint; function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end; procedure init; begin fillchar(sum,sizeof(sum),0); for i:=1 to n-1 do for j:=i to n do sum[i,j]:=sum[i,j-1]+a[j]; for i:=1 to n do f[i,i]:=a[i]; end; procedure work; begin for i:=n-1 downto 1 do for j:=i+1 to n do f[i,j]:=sum[i,j]-min(f[i,j-1],f[i+1,j]); end; begin readln(n); for i:=1 to n do read(a[i]); init; work; writeln(f[1,n],' ',sum[1,n]-f[1,n]); end.