最小邮票数

题目描述

    有若干张邮票,要求从中选取最少的邮票张数凑成一个给定的总值。     如,有1分,3分,3分,3分,4分五张邮票,要求凑成10分,则使用3张邮票:3分、3分、4分即可。

输入描述:

    有多组数据,对于每组数据,首先是要求凑成的邮票总值M,M<100。然后是一个数N,N〈20,表示有N张邮票。接下来是N个正整数,分别表示这N张邮票的面值,且以升序排列。

输出描述:

      对于每组数据,能够凑成总值M的最少邮票张数。若无解,输出0。


  起初的想法类似于先从小到大排序,然后每次使用面额最大的邮票,类似于count[sum] = count[sum - maxNumber] + 1。 发现AC不过,然后突然想到如果面值是5,8,9。要凑总数13的话,那我肯定错了。
  仔细一想,其实就是动态规划。
  给出错误代码:
#include<iostream>

using namespace std;

int assemble(int number, int arr[], int rear)
{
    if(number == 0)
    {
        return 0;
    }else if(number < 0)
    {
        return 27;
    }
    while(arr[rear] > number)
    {
        rear--;
    }
    rear--;
    return assemble(number - arr[rear + 1], arr, rear) + 1;
}
int main()
{
    int m, n, rear;
    while(cin>>m>>n)
    {
        rear = n;
        int arr[n];
        int i = 0;
        while(rear)
        {
            cin>>arr[i];
            rear--;
            i++;
        }
        int out = assemble(m, arr, n - 1);
        if(out >= 20)
        {
            cout<<0;
        }
        else {
            cout<<out;
        }
    }
}

再给出AC代码:

#include<iostream>
#include<vector>
#define mmax 27;
using namespace std;
int min(int a,int b){return a<b?a:b;}
int main()
{
    int m,n;
    while(cin>>m)
    {
        cin>>n;
        int c[n];
        for(int i=0;i<n;i++)
            cin>>c[i]; 
        int dp[m+1];
        for(int i=0;i<=m;i++)
            dp[i]=mmax;
        dp[0]=0;
        for(int i=0;i<n;i++)  
        {                     
            for(int j=m;j>=0;j--)  
            {
                if(j-c[i]>=0&&dp[j-c[i]]!=mmax)
                {
                    dp[j]=min(dp[j],dp[j-c[i]]+1);
                }
            }
        }
        if(dp[m]==mmax) cout<<0<<endl;
        else cout<<dp[m]<<endl;
    }
}

 

posted @ 2018-12-30 19:55  Stoves  阅读(331)  评论(0编辑  收藏  举报