codeves天梯 邮票面值设计

探讨了在给定最多可粘贴的邮票数量N和不同种类邮票数量K的情况下,如何设计邮票面值以获得从1到某个最大值MAX内的所有邮资值。通过DFS与动态规划相结合的方法找到了最优面值组合。

给定一个信封,最多只允许粘贴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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值