codeves天梯 邮票面值设计

来源:互联网 发布:360新一代安全网络导航 编辑:程序博客网 时间:2024/04/29 08:01

给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+K≤40)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值MAX,使在1~MAX之间的每一个邮资值都能得到。

   

    例如,N=3,K=2,如果面值分别为1分、4分,则在1分~6分之间的每一个邮资值都能得到(当然还有8分、9分和12分);如果面值分别为1分、3分,则在1分~7分之间的每一个邮资值都能得到。可以验证当N=3,K=2时,7分就是可以得到的连续的邮资最大值,所以MAX=7,面值分别为1分、3分。

分析:一开始没什么头绪,后来看了下题解,其实这题的做法是dfs兼动态规划,做法就是每次先d出一个邮票的面值,在通过算总数的动态规划(很像01背包)进行统计更新。动态转移方程:f[i]:=max(f[i],f[i-a[i]]+1);

const  maxn=200;var  f:array [0..maxn] of longint;  a,n1:array [1..maxn] of longint;  n,k,max:longint;procedure init;var  i,j:longint;begin  readln(n,k);end;function try(x:longint):longint;var  i,j:longint;begin  f[0]:=0;  i:=0;  repeat    inc(i);    f[i]:=maxint;    for j:=1 to x do      if a[j]>i then        break      else        if f[i-a[j]]+1<f[i] then          f[i]:=f[i-a[j]]+1;  until f[i]>n;  exit(i-1);end;procedure dfs(dep:longint);var  i,t:longint;begin  if dep>k then    begin      t:=try(dep);      if t>max then        begin          max:=t;          n1:=a;        end;      exit;   end;  t:=try(dep-1)+1;  for i:=a[dep-1]+1 to t do    begin      a[dep]:=i;      dfs(dep+1);    end;end;procedure work;var  i:longint;begin  init;  a[1]:=1;  dfs(2);  for i:=1 to k do    write(n1[i],' ');  writeln;  write(max);end;begin  work;end.

0 0