zoukankan      html  css  js  c++  java
  • 牛客网——代金券组合

    题目:链接:https://www.nowcoder.com/questionTerminal/5d2405da8d364eafbaca1de9bc2a0d4e?answerType=1&f=discussion
    来源:牛客网


    [编程题]代金券组合
    • 热度指数:766 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M

    近期某商场由于周年庆,开启了“0元购”活动。活动中,消费者可以通过组合手中的代金券,实现0元购买指定商品。

    聪明的小团想要用算法来帮助他快速计算:对于指定价格的商品,使用代金券凑出其价格即可,但所使用的代金券总面额不可超过商品价格。由于代金券数量有限,使用较少的代金券张数则可以实现价值最大化,即最佳优惠。

    假设现有100元的商品,而代金券有50元、30元、20元、5元四种,则最佳优惠是两张50元面额的代金券;而如果现有65元的商品,则最佳优惠是两张30元代金券以及一张5元代金券。

    请你帮助小团使用一段代码来实现代金券计算。




    输入描述:
    多组输入输出,读到s=0时结束
    输入可以有多个测试样例,每个测试由两行组成。

    其中第一行包含一个整数P,表示商品的价格,1≤P≤10000;输入P为0时表示结束。

    第二行包含若干整数,使用空格分割。其中第一个整数N(1≤N≤20)表示有多少种代金券,其后跟随M个整数,表示手中持有的代金券面额(1≤N≤1000),每种代金券数量不限。


    输出描述:

    找到最少张数的代金券,使其面额恰好等于商品价格。输出所使用的代金券数量;

    如果有多个最优解,只输出其中一种即可;

    如果无解,则需输出“Impossible”。

    示例1

    输入

    65
    4 50 30 20 5
    0

    输出

    3以上,就是全部题目,相信学过DP的朋友们,都能看出来是个DP的动态规划题目,引入一个数组F[n]来记录0——cash元的最优解有几张(n 就是遍历 0 - cash 的,因为你最终的答案是建立在cash之前的金额上的),想要遍历出最优解首先得把F[n] 初始一个很大的值,在遍历中用min()函数,如果遇到最优解的方法将最优解的小值替换掉较大的解。
    如果所有0-cash所有的钱都遍历完了,但f[cash] 还等于你初始设置的呢个数,则代表没有代金券能刚好抵消商品价格,就是没有最优的解,所以输出Impossible,反之,输出f[cash]最优解。
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int main(){
        int cash,s;
        int coins[21];
        while(~scanf("%d",&cash)&& cash != 0)
        {
            scanf("%d",&s);
            for(int i = 0 ; i < s ; i ++)
            {
                scanf("%d",&coins[i]);
            }
            
            sort(coins,coins+s);
            
               int F[10000];
               for(int i = 0 ; i <= cash ; i ++){
                   F[i] = cash +1;                // 这一块就是为了初始值,设一个很大的数字就行
            }
            
            F[0] = 0;         // 在0 元时,最优解就是0张;
         for(int j = 0 ; j <= cash ; j ++)   //枚举金钱数 
    { for(int k = 0 ; k < s ; k ++) { if(j < coins[k]) // 因为代金券不能大于金钱额度,所以遍历到直接跳出了,毕竟经过排序,后面的代金券的值都大于目前代金券的值。 break; else F[j] = min(F[j-coins[k]]+1 ,F[j]); //反之,如果小于,则将金钱额度-目前这个代金券 得到的是上一个没用这次代金券的值, 将使用本次代金券的值 和 不使用代金券的值 相对比,取最优解。+1的原因是F数组里存的最优解是几张,如果使用这次代金券则张数必加1 } } if(F[cash] == cash+1) cout << "Impossible" << endl; else cout << F[cash] << endl; } }
  • 相关阅读:
    事务传播机制,搞懂。
    洛谷 P1553 数字反转(升级版) 题解
    洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is Here 题解
    洛谷 P1055 ISBN号码 题解
    洛谷 P2141 珠心算测验 题解
    洛谷 P1047 校门外的树 题解
    洛谷 P1980 计数问题 题解
    洛谷 P1008 三连击 题解
    HDU 1013 题解
    HDU 1012 题解
  • 原文地址:https://www.cnblogs.com/wtzmz/p/12920099.html
Copyright © 2011-2022 走看看