给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+K≤40)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值MAX,使在1~MAX之间的每一个邮资值都能得到。(n<=10,k<=5)
注:这是一道经典的搜索与动态规划结合的题目。题目中的描述告诉我们,我们要做的有两个步骤:1.设计出n张邮票的组合 2.对这个组合进行dp,求出最大的连续可能贴出的邮票(过程与usaco中3.1最后一题相似),更新答案。
关键就是如何进行搜索与动态规划的结合。我们可以想到,由于最多只能有k种面值,这样就可以以第几种为搜索参数,dfs第i种。如果i大于k,证明已经达到k种,这样便进行dp,更新答案;反之若不够k种,便要搜索第k+1种,注意第k+1种有一个范围,min和max,很显然min=a[i-1]+1,max的计算要用到dp过程,max即是前i-1种能达到的连续最大值+1,即dp(i-1)+1。
代码:
var
ans,a:array[0..200] of longint;
f:array[0..1000] of longint;
n,m,i,j,k,maxn:longint;
function dp(x:longint):longint;
var
i,j:longint;
begin
f[0]:=0; f[1]:=1;
i:=1;
while f[i]<=n do
begin
inc(i);
f[i]:=n+1;
for j:=1 to x do
if i-a[j]>=0 then
if f[i-a[j]]+1<f[i] then
f[i]:=f[i-a[j]]+1;
end;
dec(i);
if i>=maxn then
begin
maxn:=i;
ans:=a;
end;
exit(i);
end;
procedure dfs(x:longint);
var
i,j,max,min:longint;
begin
if x>k then
begin
if a[k]*n>maxn then
dp(k);
end
else
begin
min:=a[x-1]+1; max:=dp(x-1)+1;
for i:=min to max do
begin
a[x]:=i;
dfs(x+1);
end;
end;
end;
begin
readln(n,k);
maxn:=0;
a[1]:=1;
dfs(2);
write(1);
for i:=2 to k do write(' ',ans[i]);
writeln;
writeln('MAX=',maxn);
end.