1.数据分析:每个信封最多贴K张邮票,每张邮票的数量不超过n,可用一个数组来表示能够表示贴出每种邮资。
<1>阶段:能够构成每个面值为阶段。比如能构成的面值为1到V,那么总共为V个阶段。
<2>状态:dp[i]表示构成面值i所需要的最少邮票数.
<3>决策:对于样例数据1和3两种面值的邮票:
构成邮资0:所需要邮票张数为0张,dp[0]=0;
构成邮资1:只能用1分的邮票,所需要邮票张数1张,dp[1]=1;
构成邮资2:只能用1分的邮票,所需要邮票张数2张,dp[2]=1;
构成邮资3:
*1.若选择使用一张1分的邮票,dp[3]=dp[2]+1=3………dp[3-1]+1
*2.若选择使用一张3分的邮票,dp[3]=dp[0]+1=1………dp[3-3]+1
dp[3]=min{dp[2]+1,dp[0]+1}=1;
构成邮资4:
*1.若选择使用一张1分的邮票,dp[4]=dp[3]+1=2………dp[3-1]+1
*2.若选择使用一张3分的邮票,dp[4]=dp[1]+1=1………dp[3-3]+1
dp[4]=min{dp[3]+1,dp[1]+1}=2;
<4>状态转移方程:dp[i]=min{dp[i-a[j]]+1} i>=a[j] 1<=j<=n f[i]<=k;
算法:深度优先搜索+动态规划
type arr=array[0..40] of longint; var ans,a:arr; i,n,k,best:longint; function min(a,b:longint):longint; begin if a<b then exit(a) else exit(b); end; function dp(a:arr):longint; var i,j,t:longint; f:array[0..600] of longint; begin fillchar(f,sizeof(f),$7f); f[0]:=0; t:=min(600,a[a[0]]*n); for i:=1 to t do begin for j:=1 to a[0] do if i>=a[j] then f[i]:=min(f[i],f[i-a[j]]+1); if f[i]>n then break; end; if i<>(a[a[0]]*n) then dec(i); exit(i); end; procedure dfs(step,max:longint;a:arr); var i,nmax:longint; na:arr; begin for i:=a[step-1]+1 to max+1 do begin na:=a; na[step]:=i; na[0]:=step; nmax:=dp(na); if step=k then begin if nmax>best then begin ans:=na; best:=nmax; end; end else if step<k then dfs(step+1,nmax,na); end; end; begin readln(n,k); if k=1 then begin writeln(1); writeln('MAX=',n); halt; end; a[0]:=1;a[1]:=1; dfs(2,n,a); for i:=1 to k do write(ans[i],' '); writeln; writeln('MAX=',best); end.
参考博客:blog.csdn.net/y1196645376/article/details/42197485(神犇)
喜欢就收藏一下,vic私人qq:1064864324,加我一起讨论问题,一起进步^-^