求函数最大值(CTSC'95)

时间:2022-08-04 15:32:12

一、问题描述

    已知三个函数A,B,C值如下表所示。自变量取值为0-10的整数。 请用动态规划的方法求出一组x,y,z。使得A(x)+B(y)+C(z)为最大,并且满足x*x+y*y+z*z<NN由键盘输入。

 X    0   1   2   3   4   5   6   7   8   9  10

A(x)  2   4   7  11  13  15  18  22  18  15  11

B(x)  5  10  15  20  24  18  12   9   5   3   1

C(x)  8  12  17  22  19  16  14  11   9   7   4

二、思路分析

本题已经说明了算法是动态规划,我们接下来要做的就是求他的状态转移方程。稍加分析可得到状态转移方程:

F[I,j]=max(f[i-1,j-x*x]+p[I,x]);

其中,A(X)=p[1,x],  B(X)=P[2,X],  C(X)=P[3,X];

F[I,J]表示前I个函数的自变量平方和为j时函数和的最大值。易证,此规划方程满足无后效性。得到函数最大值后,我们再用自底向上追溯的方法求出X,Y,Z,的值,具体实现请看程序。

三、参考程序

program CTSC_95_4;

const

  f  : array[1..3,0..10] of integer =            {函数}

  ((2,  4,  7, 11, 13, 15, 18, 22, 18, 15, 11),

   (5, 10, 15, 20, 24, 18, 12,  9,  5,  3,  1),

   (8, 12, 17, 22, 19, 16, 14, 11,  9,  7,  4));

var

  s  : array[1..3,0..300] of longint;  {状态S[I,J]表示前I个函数自变量值的平方和为j时函数和的最大值}

  pre: array[1..3,0..300] of integer;  {前驱数组,保存该状态是由上阶段哪个状态得到的}

  n  : longint;

 

procedure main;

var

  i,j,k,p,x,y,z : integer;

begin

  write('n=');  readlN(n);

  if n>301 then n:=301;  {如果N>301(10*10+10*10+10*10)N=301}

  fillchar(s,sizeof(s),0);

  fillchar(pre,sizeof(pre),0);

  for i := 0 to 10 do s[1,i*i] := f[1,i];

  for i := 1 to 2 do

      for j := 0 to n-1 do begin

          if s[i,j] > s[i+1,j] then

             begin s[i+1,j] := s[i,j]; pre[i+1,j] := j; end;

          for k := 0 to 10 do

              if s[i,j]+f[i+1,k]>s[i+1,j+k*k] then begin

                 p := j+k*k;

                 if p>=n then break;

                 pre[i+1,p] := j;

                 s[i+1,p] := s[i,j]+f[i+1,k];

              end;

      end;

  p := 0; k := 0;

  for i := 0 to n-1 do

      if s[3,i]>k then begin

         k := s[3,i]; p := i;

      end;

  z := trunc(sqrt(p-pre[3,p])); p := pre[3,p];  {求出Z}

  y := trunc(sqrt(p-pre[2,p])); p := pre[2,p];  {求出Y}

  x := trunc(sqrt(p)); {求出X}

  writeln('Max=',k);

  writeln('A=',x,',','B=',y,',','C=',z);

end;

 

begin

main;

end.