• 1047 邮票面值设计 (DFS+DP)


    题目描述 Description

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

    输入描述 Input Description

    N和K

    输出描述 Output Description

    每种邮票的面值,连续最大能到的面值数。数据保证答案唯一。

    样例输入 Sample Input

    3 2

    样例输出 Sample Output

    1 3

    MAX=7

    分析:

    不断的暴力枚举每一种的面值的结果,第i面值的范围,可以有第i-1钟面值得出范围,a[i]是不断变化枚举的面值的数组,所以需要res[i]数组来记录正确答案

    dp[i]表示到达i的结果需要最少的张数。

    大神的解释

    /*
    这个题目知道是深搜,但是邮票面值的上界在深搜中不好确定,只知道下界是>前一个,这里就妙在用DP解决了深搜的上界,和当前邮票可以取到的连续最大值
    */
    /*
    ①搜索。对每一步,枚举邮票面值,然后搜索下一张邮票面值并更新最优解。
    
    ②完全背包确定搜索范围。
    
    假设现在枚举到第 i 张邮票面值,第 i-1 张邮票面值为a[i-1],前 i-1 张邮票得到的最大连续值为x,则第 i 张邮票面值的范围就为 [a[i-1]+1,x+1];
    
    假设现在有 n 张邮票,怎么得到其最大连续值呢?
    
    用 f[i] 记录达到数值 i 所需的最小邮票数量,初始化为一个极大值。然后用完全背包算出 f[i] 的值,从 0 开始,第一个f[i]>n,则 i-1 就为最大连续值。
    
    */
    #define N 50
    #include<iostream>
    using namespace std;
    #define inf 500
    #include<cstdio>
    #include<cstring>
    int b[N],ans=0,a[N],f[inf];
    int n,k;
    void dfs(int m)
    {
        memset(f,0x3f,sizeof(f));
        f[0]=0;
        int i;
        for(i=1;i<=inf;++i)
        {
            for(int j=1;j<=m&&a[j]<=i;++j)
              f[i]=min(f[i],f[i-a[j]]+1);/*完全背包是可以把物品空间的内外循环交换位置的,反正都是无限放*/
            if(f[i]>n)/*当前m种邮票所能取到的最大值*/
            {
                i--;
                if(i>ans)
                {
                    ans=i;
                    for(int l=1;l<=m;++l)
                     b[l]=a[l];
                }
                break;
            }
        }
        
        if(m==k) return;
        for(int j=i+1;j>a[m];--j)
        {/*下一张邮票的范围*/
            a[m+1]=j;
            dfs(m+1);
        }
    } 
    int main()
    {
        scanf("%d%d",&n,&k);
        a[1]=1;
        dfs(1);
        for(int i=1;i<=k;++i)
          printf("%d ",b[i]);
        printf("
    ");
        printf("MAX=%d
    ",ans);
        return 0;
    }
    View Code

    积极敲的

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=2000000+100;
    const int INF=0x3f3f3f3f;
    int dp[maxn];
    int a[50],res[50];
    int ans=0;
    int n,k;
    
    
    
    void work()
    {
        dp[0]=0;
        int i=0;
        while(dp[i]<=n)
        {
            i++;
            dp[i]=INF;
            for(int j=1 ; j<=k && a[j]<=i ; j++)
            dp[i]=min(dp[i],dp[i-a[j]]+1);
        }
        if(i-1>ans)
        {
            ans=i-1;
            for(int i=1 ; i<=k ; i++)
            {
                res[i]=a[i];
            }
        }
    }
    void dfs(int m)
    {
        if(m==k+1)
        {
            work();
            return ;
        }
        for(int j=a[m-1]+1 ; j<=a[m-1]*n+1 ; j++)
        {
            a[m]=j;
            dfs(m+1);
    
        }
    }
    int main( )
    {
        scanf("%d%d",&n,&k);
        a[1]=1;
        dfs(1);
        for(int i=1 ; i<=k ; i++)
        printf("%d ",res[i]);
        printf("
    MAX=%d
    ",ans);
    }
    View Code
  • 相关阅读:
    mysql随手记
    Exception 和 RuntimeException区别
    数据结构与算法
    Idea快捷键
    eclipse快捷键
    了解Lua语言中的_index,newindex,rawget和rawset
    Cocos2d-x CCNotificationCenter 通知中心
    LUA-赋值语句
    CCOrbitCamera:create
    类型和值
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/9756104.html
Copyright © 2020-2023  润新知