codevs动态规划 数字游戏

  • 丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。

    例如,对于下面这圈数字(n=4m=2):

                                      2

                       4                           -1

                                     3

    当要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对10取模的结果均为非负值。

    丁丁请你编写程序帮他赢得这个游戏。

  • 分析:其实是一道很简单的题,题目中就是要求出那一个地方放括号,使最后mod10相乘的值最大,动态规划中就只是去求括号的位置。(最大值会求,最小值就懒得说了==)。
  • 动态转移方程: f1[j,k]:=max(f1[j,k],f1[j-1,l]*(quyu(s[k+i]-s[l+i],10)))
  •              f2[j,k]:=min(f2[j,k],f2[j-1,l]*(quyu(s[k+i]-s[l+i],10)))
  • const
      maxn=50;
    
    var
      a,v:array[0..maxn] of longint;
      f:array[0..9,0..maxn] of longint;
      n,m,i:longint;
    
    function fx(a,b:longint):longint;
    var
      i:longint;
    begin
      fx:=0;
      for i:=a to b do
        fx:=fx+v[i];
      fx:=(fx+100000) mod 10;
    end;
    
    procedure min;
    var
      i,j,k,t,ans,min1:longint;
    begin
      min1:=maxlongint;
      for i:=1 to n do
        begin
          for j:=1 to n do
            v[j]:=a[(i+j-1) mod n];
          v[n-i+1]:=a[n];
          f[0,1]:=v[1];
          for j:=1 to n do
            f[0,j]:=fx(1,j);
          for j:=1 to m-1 do
            for k:=j+1 to n do
              begin
                f[j,k]:=maxlongint;
                for t:=j to k-1 do
                  begin
                    ans:=fx(t+1,k);
                    if f[j,k]>ans*f[j-1,t] then
                      f[j,k]:=ans*f[j-1,t];
                end;
          end;
          if f[m-1,n]max1 then
            max1:=f[m-1,n];
      end;
      writeln(max1);
    end;
    
    begin
      readln(n,m);
      for i:=1 to n do
        readln(a[i]);
      min;
      max;
    end.
    

你可能感兴趣的:(动态规划)