zoukankan      html  css  js  c++  java
  • [codevs1047]邮票面值设计 dp+dfs

    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;

     算法:深度优先搜索+动态规划

         如果已知邮票的不同面值,可以用动态规划求出这些不同面值的邮票能组合出的最大连续数:
                            设dp[i]表示已知面值的邮票组合出面值为i所需要的最小邮票数,我们把已知的q种不同的邮票面值存在num中,则有状态转移方程:
                                                     dp[i]=min{dp[i-num[j]]+1}      
        最后随着深度搜索不断枚举可能的面值组合,然后不断更新最大值即可
    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,加我一起讨论问题,一起进步^-^

     

     

  • 相关阅读:
    java.lang.NoClassDefFoundError: org.junit.runner.Runner
    SpringMVC 八大注解
    spring @autowired使用总结
    Git使用入门
    N21_栈的压入弹出序列。
    N20_包含min函数的栈
    N19_顺时针打印指针
    N17_判断树B是不是树A的子结构
    N16_合并两个排序链表
    N15_反转链表后,输出新链表的表头。
  • 原文地址:https://www.cnblogs.com/victorslave/p/4827317.html
Copyright © 2011-2022 走看看