• 动态规划练习题(1)


    1、0/1背包(package.pas)

    AYYZOJ p1472

     1 program p1472;
     2 const
     3   maxm=200; maxn=30;
     4 var
     5   m,n,i,j:integer;
     6   c,w:array[1..maxn] of integer;
     7   f:array[0..maxn,0..maxm] of integer;
     8 function max(x,y:integer):integer;
     9 begin
    10   if x>y then max:=x else max:=y;
    11 end;
    12 begin
    13   readln(m,n);
    14   for i:=1 to n do readln(w[i],c[i]);
    15   for i:=1 to n do
    16    for j:=1 to m do
    17     begin
    18       if j>=w[i] then f[i,j]:=max(f[i-1,j-w[i]]+c[i],f[i-1,j])
    19         else f[i,j]:=f[i-1,j];
    20     end;
    21  writeln(f[n,m]);
    22 end.
    参考程序

    2、采药(medic.pas)

    AYYZOJ p1052

    COGS p68

     1 const
     2   maxm=1000; maxn=100;
     3 var
     4   f:array[0..maxn,0..maxm] of integer;
     5   w,c:array[1..maxn] of integer;
     6   m,n,i,j:integer;
     7 
     8 function max(x,y:integer):integer;
     9 begin
    10   if x>y then max:=x else max:=y
    11 end;
    12 
    13 begin
    14 assign(input,'medic.in');
    15 reset(input);
    16 assign(output,'medic.out');
    17 rewrite(output);
    18   readln(m,n);
    19   for i:=1 to n do readln(w[i],c[i]);
    20   fillchar(f,sizeof(f),0);
    21    for i:=1 to n do
    22     for j:=1 to m do
    23      if j>=w[i] then f[i,j]:=max(f[i-1,j-w[i]]+c[i],f[i-1,j])
    24                else f[i,j]:=f[i-1,j];
    25   writeln(f[n,m]);
    26 close(input);
    27 close(output);
    28 end.
    参考程序

    3、开心的金明(happy.pas)

    AYYZOJ p1059

    COGS p71

     1 var
     2   f:array[0..30000] of longint;
     3   w,c:array[1..30000] of longint;
     4   i,j,m,n,ans:longint;
     5 begin
     6 assign(input,'happy.in');
     7 reset(input);
     8 assign(output,'happy.out');
     9 rewrite(output);
    10   readln(m,n);
    11   for i:=1 to n do readln(w[i],c[i]);
    12   fillchar(f,sizeof(f),0);
    13    for i:=1 to n do
    14     for j:=m downto w[i] do
    15      if f[j-w[i]]+c[i]*w[i]>f[j] then f[j]:=f[j-w[i]]+c[i]*w[i]
    16       else f[j]:=f[j]+c[j]*w[j];
    17    writeln(f[m]);
    18 close(input);
    19 close(output);
    20 end.
    参考程序1
     1 var
     2   n,m,i,j:integer;
     3   v,p:array[1..25] of longint;
     4   dp:array[0..30000] of longint;
     5   function max(x,y:longint):longint;
     6   begin if x>y then max:=x else max:=y; end;
     7 begin
     8   assign(input,'happy.in'); assign(output,'happy.out');
     9   reset(input); rewrite(output);
    10   readln(n,m);
    11   for i:=1 to m do
    12     begin
    13       readln(v[i],p[i]);
    14       p[i]:=p[i]*v[i];
    15     end;
    16   for i:=1 to m do
    17     for j:=n downto v[i] do
    18       dp[j]:=max(dp[j],dp[j-v[i]]+p[i]);
    19   writeln(dp[n]);
    20   close(input); close(output);
    21 end.
    参考程序2

    4、装箱问题(box.pas)

    AYYZOJ p1021

    COGS p1089

    我的思路:使剩余空间最小,则可以设每件物品的价值c[i]=每件物品的体积w[i] 。转化为0/1背包问题,最后输出V-dp[v]即可

     1 var
     2   v,n,i,j:longint;
     3   w,c:array[1..30] of longint;
     4   dp:array[0..20000] of longint;
     5 function max(x,y:longint):longint;
     6 begin
     7   if x>y then max:=x else max:=y;
     8 end;
     9 begin
    10 assign(input,'npack.in');
    11 reset(input);
    12 assign(output,'npack.out');
    13 rewrite(output);
    14   readln(v);
    15   readln(n);
    16   for i:=1 to n do begin readln(w[i]); c[i]:=w[i]; end;
    17    for i:=1 to n do
    18     for j:=v downto w[i] do
    19      dp[j]:=max(dp[j-w[i]]+c[i],dp[j]);
    20    writeln(v-dp[v]);
    21 close(input);
    22 close(output);
    23 end.
    我的程序

    另一种思路:{f[j]是布尔数组,表示前i件物品正好装满容积为j的箱子,最后从后往前扫描布尔数组f,找到最大值}

     1 var
     2  f:array [0..20000] of boolean;
     3  box:array [0..30] of integer;
     4  n,v,m,i,j:longint;
     5 begin
     6  readln(v);
     7  readln(n);
     8  for i:=1 to n do read(box[i]);
     9  for i:=0 to v do f[i]:=false;
    10  f[0]:=true;
    11  for i:=1 to n do
    12    for j:=v downto box[i] do
    13      if f[j-box[i]] then f[j]:=true;
    14  for i:=v downto 0 do if f[i]=true then
    15    begin
    16       writeln(v-i);
    17       halt;
    18    end;
    19 end.
    老师给的程序

    5、竞赛真理(truth.pas/c/cpp)

    AYYZOJ p1493

     1 var
     2   n,t,i,j:longint;
     3   f:array[0..1080000] of longint;
     4   w1,t1,w2,t2:array[0..30] of longint;
     5 function max(a,b:longint):longint;
     6 begin
     7   if a>b then max:=a
     8    else max:=b;
     9 end;
    10 begin
    11   fillchar(f,sizeof(f),0);
    12   readln(n,t);
    13   for i:=1 to n do
    14    readln(w1[i],t1[i],w2[i],t2[i]);
    15   for i:=1 to n do
    16    for j:=t downto 1 do
    17    begin
    18      if j>=t1[i] then
    19       f[j]:=max(f[j-t1[i]]+w1[i],f[j]);
    20      if j>=t2[i] then
    21       f[j]:=max(f[j-t2[i]]+w2[i],f[j]);
    22    end;
    23   writeln(f[t]);
    24 end.
    我的程序
     1 var a,b:array[1..30,1..2] of longint;
     2     f:array[0..1080000] of longint;
     3     i,j,n,time:longint;
     4 begin
     5   readln(n,time);
     6   for i:=1 to n do
     7     read(a[i,1],b[i,1],a[i,2],b[i,2]);
     8   for i:=1 to n do
     9     for j:=time downto 1 do begin
    10       if j>=b[i,1] then
    11         if f[j]<f[j-b[i,1]]+a[i,1] then f[j]:=f[j-b[i,1]]+a[i,1];
    12       if j>=b[i,2] then
    13         if f[j]<f[j-b[i,2]]+a[i,2] then f[j]:=f[j-b[i,2]]+a[i,2];
    14     end;
    15   writeln(f[time]); 
    16 end.
    老师给的程序

     【问题分析】

    本题是背包问题的应用,可用动态规划来做,设 f(i,x)表示前i道题,总时间不超过x的最大得分则动态转移方程为:

        f(i,x)=max(f(i-1,x-T1[i])+W1[i] ,f(i-1,x-T2[i])+W2[i],f(i-1,x))

    f(n,t)即为最优解,边界条件为f(0,x)=0 ,f(i,0)=0;

    由于这道题目中给出的时间T的取值较大达到1080000,如果定义成二维数组即使在Free Pascal中也无法实现,我们不妨把f(n,t)定义成两个一维数组f1(i)和f2(i),由于上次的计算结果只对当前的计算有用,所以我们把这两个数组迭代使用,直到计算出最后的结果。

     1 【参考程序】1 2 program truth;
     3   const maxn=30;maxt=1080000;
     4   var
     5     total,n,k,i,j:longint;
     6     t1,t2,w1,w2:array[1..maxn] of longint;
     7     f1,f2:array[0..maxt] of longint;
     8     fw:array[0..maxt] of longint;
     9   function max(a,b,c:longint):longint;
    10     begin
    11       if a<b then a:=b;
    12       if a<c then a:=c;
    13       max:=a;
    14     end;
    15   function max2(a,b:longint):longint;
    16     begin
    17       if a<b then a:=b;
    18       max2:=a;
    19     end;
    20   begin
    21     assign(input,'truth.in');
    22     reset(input);
    23     assign(output,'truth.out');
    24     rewrite(output);
    25     readln(n,k);
    26     for i:=1 to n do
    27       readln(w1[i],t1[i],w2[i],t2[i]);
    28     fillchar(f1,sizeof(f1),0);
    29     fillchar(f2,sizeof(f2),0);
    30     for i:=1 to n do
    31      begin
    32       for j:=1 to k do
    33         if (j>=t1[i]) and (j>=t2[i])
    34           then f2[j]:=max(f1[j-t1[i]]+w1[i],f1[j-t2[i]]+w2[i],f1[j])
    35           else
    36             if j>=t1[i] then f2[j]:=max2(f1[j-t1[i]]+w1[i],f1[j])
    37               else if j>=t2[i] then f2[j]:=max2(f1[j-t2[i]]+w2[i],f1[j])
    38                      else f2[j]:=f1[j];
    39       for j:=0 to k do f1[j]:=f2[j];
    40      end;
    41     writeln(f2[k]);
    42     close(output);
    43     close(input)
    44   end.
    45 【参考程序】2
    46 var a,b:array[1..30,1..2] of longint;
    47     f1:array[0..600000] of longint;
    48     i,j,n,time:longint;
    49 begin
    50   assign(input,'truth.int');reset(input);
    51 assign(output,'truth.out');rewrite(output);
    52   readln(n,time);
    53   for i:=1 to n do
    54     read(a[i,1],b[i,1],a[i,2],b[i,2]);
    55   for i:=1 to n do
    56     for j:=time downto 1 do begin
    57       if j>b[i,1] then
    58         if f1[j]<f1[j-b[i,1]]+a[i,1] then f1[j]:=f1[j-b[i,1]]+a[i,1];
    59       if j>b[i,2] then
    60         if f1[j]<f1[j-b[i,2]]+a[i,2] then f1[j]:=f1[j-b[i,2]]+a[i,2];
    61      { f1:=f2;}
    62     end;
    63   writeln(f1[time]); 
    64 
    65 end. 
    66 
    67 参考程序3:
    68 var
    69     i,j,n,t:longint;
    70     v1,w1,v2,w2:array[1..30]of longint;
    71     f:array[0..1080000]of longint;
    72 begin
    73     assign(input,'truth.in');
    74     reset(input);
    75     assign(output,'truth.out');
    76     rewrite(output);
    77     readln(n,t);
    78     for i:=1 to n do read(v1[i],w1[i],v2[i],w2[i]);
    79     for i:=1 to n do
    80         for j:=t downto 0 do begin
    81             if(j>=w1[i])and(f[j-w1[i]]+v1[i]>f[j])then f[j]:=f[j-w1[i]]+v1[i];
    82             if(j>=w2[i])and(f[j-w2[i]]+v2[i]>f[j])then f[j]:=f[j-w2[i]]+v2[i];
    83         end;
    84     writeln(f[t]);
    85     close(input);
    86     close(output);
    87 end.
    参考程序
  • 相关阅读:
    Linux环境下入侵工具Knark的分析及防范 java程序员
    六个步骤即可防范ARP地址欺骗类病毒 java程序员
    巧用命令行 揪出ARP欺骗病毒母机方法 java程序员
    poj3264Balanced Lineup(线段树RMQ)
    有了1A的把握再去提交
    poj2828Buy Tickets(线段树 单点更新+区间求和+区间第K值)
    poj2513Colored Sticks(无向图判欧拉路、回路+trie树)
    ACM数学(转)
    sdut2381Broken Keyboard
    sdut2383Decode the Strings(循环节)
  • 原文地址:https://www.cnblogs.com/vacation/p/5404156.html
Copyright © 2020-2023  润新知