取数游戏 纪中 1308 蜜汁dp

Description

  Alice想让Bob陪他去看《唐山大地震》,但由于Bob是个很感性的人,怕流泪不想去,但又不好意思以这个作为拒绝的理由,便提出玩一个游戏。
  N个正整数围成一圈,规则如下:
  •两个玩家轮流取数;
  •最开始先手的玩家可以取任意一个数x;
  •从第二步开始当前玩家只能取x(上一玩家刚刚取的数)左右两边相邻的数;
  •直到取完所有的数,游戏结束;
  •取得较多奇数的玩家获胜。
  Bob为了显示大度,让Alice先取,但他忘了自己和Alice都是绝顶聪明之人,现在Alice请你帮他计算第一步有多少种取法使得最终获得胜利。

Input

  第一行包含一个整数N(1<=N<=100),表示数的个数。第二行包含N个正整数,每个数都在1到1000之间,任意两个数互不相同。

Output

  输出Alice第一步有多少种取法。
 

分析

这个东西有一些玄。
首先我们设一个s[i,j]表示i—j区间中奇数的个数。

f[i,j]=max(s[i,j]f[i+1,j],s[i,j]f[i,j1])

可以枚举Alice的第一次选择。
自行画图理解。

代码

va-r 
  a:array[0..200] of longint;
  s:array[0..200] of longint;
  f:array[0..200,0..200] of longint;
  i,j,k,l:longint;
  ans:longint;
  n:longint;

function max(x,y:longint):longint;
begin
  if x>y then max:=x
         else max:=y;
end;

begin
  readln(n);
  for i:=1 to n do
    read(a[i]);
  for i:=1 to n do
    begin
      k:=0;
      fillchar(f,sizeof(f),0);
      fillchar(s,sizeof(s),0);
      for j:=1 to n do
        begin
          k:=k+1;
          if a[j] mod 2=1
            then
              begin
                //k:=k+1;
                f[k,k]:=1;
              end;
        end;
      for j:=1 to n do
        begin
          s[j]:=s[j-1];
          if a[j] mod 2=1
            then s[j]:=s[j]+1;
        end;
      for k:=1 to n-2 do
        for j:=1 to n-k do
          begin
            l:=k+j;
            f[j,l]:=max(s[l]-s[j-1]-f[j+1,l],s[l]-s[j-1]-f[j,l-1]);
            l:=l;
          end;
      f[1,n]:=s[l]-f[2,n]; 
      if s[n] div 2+1<=f[1,n] then ans:=ans+1;
      k:=a[1];
      for j:=1 to n do
        a[j]:=a[j+1];
      a[n]:=k;
    end;
  write(ans);
end.

posted @ 2016-07-14 07:54  一个响亮的蒟蒻  阅读(248)  评论(0编辑  收藏  举报