题目大意:给出n(≤500)个数,两个人轮流取数,每次可以从数列左边或者右边取一个数,直到所有的数被取完,两个人都以最优策略取数,求最后两人所得分数。

      显然这种类型的博弈题,第一眼就是极大极小搜索+记忆化,但是我并不是很会极大极小搜索TAT。然后第二眼发现可以用DP写,而且显然比极大极小搜索好写啊。这一类的题有一个最普遍的做法,预处理出前缀和,然后f[i][j]表示从第i个数到第j个数先手可得到的最大得分,则有$$f[i][j]=sum[j]-sum[i-1]-min(f[i+1][j],f[i][j-1]);$$【第i个数到第j个数的和减去min(第i+1个数到第j个数先手可得到的最大得分,第i个数到第j-1个数先手可得到的最大得分)】

      要注意一点,由于$$f[i][j]$$需要用到$$f[i+1][j]和f[i][j-1]$$,所以我们需要枚举的是i到j这个区间的长度,先把区间长度小的计算出来,才能计算区间长度大的,一开始就被这个坑了,果然我还是太弱了= =。。。

代码如下:

var
  n,i,j,x:longint;
  f:array[0..500,0..500]of longint;
  sum:array[0..500]of longint;

function min(a,b:longint):longint;
begin
  if a<b then exit(a);
  exit(b);
end;

begin
  readln(n);
  for i:=1 to n do
  begin
    read(x);
    sum[i]:=sum[i-1]+x;//前缀和
    f[i][i]:=x;
  end;
  for j:=1 to n-1 do//枚举区间长度
  for i:=1 to n-j do//枚举起点
  f[i][i+j]:=sum[i+j]-sum[i-1]-min(f[i+1][i+j],f[i][i+j-1]);
  writeln(f[1][n],' ',sum[n]-f[1][n]);//后手为sum[n]-f[1][n]
end.
View Code

相关文章:

  • 2021-09-14
  • 2022-02-13
  • 2021-10-13
  • 2021-11-30
  • 2021-05-05
  • 2022-02-27
猜你喜欢
  • 2021-07-13
  • 2022-01-20
  • 2021-09-17
  • 2021-06-22
  • 2022-01-02
  • 2022-01-22
  • 2022-12-23
相关资源
相似解决方案