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

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

样例:

INPUT OUTPUT

N=3 K=2 1 3

    MAX=7

注:这是一道经典的搜索与动态规划结合的题目。题目中的描述告诉我们,我们要做的有两个步骤: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.

posted on 2011-08-05 10:50  shallyzhang  阅读(311)  评论(0)    收藏  举报