最小邮票数

考研复试上机题-最小邮票数

题目描述

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

输入描述:

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

输出描述:

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

示例1

输入

10
5
1 3 3 3 4

输出

3

解题思路

          本题为典型的dfs题,数据量不大,可以直接用深度搜索解决,当然在进行搜索的过程中要注意剪枝和更新构成邮票的数量。

              一、遇到以下情况我们停止搜索:

              1、当邮票总值s>n的时。

              2、当s == n 的时候,我们把邮票数number 更新成 min(number,num),然后停止搜索。

              3、当选到最后一张邮票时,停止搜索;

              4、当当前所选的邮票数大于以及能够组合成n面值的邮票数数量时,停止搜索。

             二、dfs以后,我们对number进行判断,为-1时输出0,否则输出我们的dfs值。

解题代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include<vector>
#define rep(i,s,e) for(int i = s;i<e;i++)
using namespace std;
const int maxn = 200;
struct Sovle{
    int num;
    int sumNumber = -1;
    int sum;
    int a[maxn];
    vector<int>token;
    void init(int n,int s){
        num = n;
        sum = s;
    }
    void addToken(int n){
        token.push_back(n);
        a[token.size()-1] = n;
    }
    int dfs(int x,int s,int number){
        if(s==sum){
            if(sumNumber==-1){
                sumNumber = number;
            }else{
                sumNumber = min(sumNumber,number);
            }
        }
        if(x>=num){
            return 0;
        }
        rep(i,x,num){
            s += a[i];
            number++;
            if(s<=sum){
                dfs(i+1,s,number);
            }
            number--;
            s-=a[i];
        }
        return 0;
    }
    int getDfs(){
         dfs(0,0,0);
         return sumNumber;
    }
};
int main()
{
    int n;
    while(cin>>n){
        int num;
        cin>>num;
        Sovle so;
        so.init(num,n);
        rep(i,0,num){
            int t;
            cin>>t;
            so.addToken(t);
        }
        int t = so.getDfs();
        if(t!=-1)
        cout<<t<<endl;
        else cout<<0<<endl;
    }

}

猜你喜欢

转载自blog.csdn.net/hnust_yangjieyu/article/details/82910313