一、Noip2003,数字游戏题解(环形DP)

来源:互联网 发布:淘宝售后安装平台接单 编辑:程序博客网 时间:2024/06/10 11:08

(题目描述截图自洛谷)


标签:环形DP

题解:

    首先将数组开为2倍,破环成链,用f[x,i,j]表示以第x个数为第一个数,在前i个数中分出j组可以取得的最大值。用g[x,i,j]表示以第x个数为第一个数,在前i个数中分出j组可以取得的最小值。以f数组为例,那么f[x,i,j]可以由f[x,i-1,j-1]  f[x,i-2,j-1] ......乘以a[x+i-1]得到。因为要保证在前i-k个数中可以分出j-1组,从而i-k>=j-1 ,得1<=k<=i-j+1。 从而得到状态转移方程:

                                     f[x,i,j]=max{ f[x,i-k,j-1]*a[x+i-1] } (1<=k<=i-j+1)

                                    g[x,i,j]=min{ g[x,i-k,j-1]*a[x+i-1] } (1<=k<=i-j+1)

    注意要在j=1的时候加特判。

     最后输出f[x,n,m]中的最大值,g[x,n,m]中的最小值(1<=x<=n)即可。


实现时的问题:

       1、因为开的是3维数组,导致单调的时候不易看出变量的变化。后来干脆输出所有的f,g的值,结果在提交之前忘了把                这些用来调试的输出语句删除,导致全WA。

       2、在写j(记录组数状态)的循环时,一开始直接写了:

                      for j:=1 to i do

              结果WA掉两个点。后来一方觉得改不出什么错就改成:

                      for j:=1 to min(i,m) do 

              就过了。虽然觉得这似乎无关紧要,但是加上之后还是要严谨加上省时一些。


代码实现:

       最终的代码实现如下:

Uses math;
Var n,m,i,j,k,x,l,b,s:longint;
    a:array[1..100]of longint;
    q:array[1..100,1..100]of longint;
    f,g:array[1..50,0..100,0..10]of longint;
function mx(l,r:longint):longint;
 Var i,j:longint;
 Begin
  mx:=0;
  for i:=l to r do inc(mx,a[i]);
  if mx>0 then exit(mx mod 10)
   else mx:=(100000+mx)mod 10;
 End;
Begin
 readln(n,m);
 for i:=1 to n do readln(a[i]);
 for i:=n+1 to 2*n do a[i]:=a[i-n];
 for i:=1 to 50 do
  for j:=0 to 100 do
   for k:=0 to 10 do
    Begin f[i,j,k]:=1;
          if k=0 then g[i,j,k]:=1
            else g[i,j,k]:=maxlongint; End;


 for x:=1 to n do
  for i:=1 to n do
   for j:=1 to min(i,m) do
    for k:=i-j+1 downto 1 do
     Begin if j>1 then
            Begin f[x,i,j]:=max(f[x,i,j],f[x,i-k,j-1]*mx(x+i-k,x+i-1));
                  if g[x,i-k,j-1]=maxlongint then g[x,i,j]:=g[x,i,j]
                   else g[x,i,j]:=min(g[x,i,j],g[x,i-k,j-1]*mx(x+i-k,x+i-1));
            End;
           if j=1 then
            Begin f[x,i,j]:=mx(x,x+i-1);
                  g[x,i,j]:=mx(x,x+i-1);
            End;
     End;
 b:=0; s:=maxlongint;
 for x:=1 to n do
  Begin b:=max(b,f[x,n,m]); s:=min(s,g[x,n,m]); End;
 writeln(s);
 writeln(b);
End.

           

1 0
原创粉丝点击