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