最小邮票数

邮票问题动态规划解法

题目描述

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

输入描述:


 

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

输出描述:


 

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

示例1

输入


 

1051 3 3 3 4

输出


 

3

//此题是动态规划类型的题目,每次都可以选择拿邮票或者
//不拿邮票。dp[j]是当总和<=j时的邮票的数量。
//状态转移方程为dp[j]=min(dp[j],dp[j-v[i]]+1);
//或者是不取当前邮票,或者是取
#include<iostream>
const int maxx=99999;
using namespace std;
int v[1000],dp[120];
int main()
{
    int m;
    while(cin>>m)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
           cin>>v[i];
        for(int j=0;j<=m;j++)
           dp[j]=maxx;//初始化数量为最大值
        dp[0]=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=m;j>=v[i];j--)
            {
                dp[j]=min(dp[j],dp[j-v[i]]+1);
            }
        }
        if(dp[m]>10000)cout<<"0"<<endl;
        else cout<<dp[m]<<endl;

    }
    return 0;

}



//dp如果是二维数组的话

#include<iostream>
const int maxx=999999;
using namespace std;
int value[50];//邮票的面值
int dp[25][110];//dp[i][j]表示第i张邮票凑成j面值的邮票张数
int main()
{
    int sum;
    int num;
    while(cin>>sum)
    {
        cin>>num;
        if(num==0)
        {
            cout<<"0"<<endl;
            break;
        }
        for(int i=1;i<=num;i++)
        {
            cin>>value[i];
        }
        for(int i=0;i<=num;i++)
            dp[i][0]=0;
        for(int j=0;j<=sum;j++)
        {
            dp[0][j]=maxx;
        }
        for(int i=1;i<=num;i++)
        {
            for(int j=1;j<=sum;j++)
            {
                if(j<value[i])
                {
                    dp[i][j]=dp[i-1][j];
                }
                else dp[i][j]=min(dp[i-1][j],dp[i-1][j-value[i]]+1);
            }
        }
        if(dp[num][sum]==maxx)cout<<"0"<<endl;
        else cout<<dp[num][sum]<<endl;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值