【题解】邮票问题(stamps)

2 篇文章 0 订阅
2 篇文章 0 订阅

题目描述

  给定一个信封,最多只允许粘贴N(N<=100)张邮票,我们现在有M(M<=100) 种邮票,面值分别为:x1,x2,...,xm分(Xi<=255,为正整数),并假设各种邮票都有足够多张。

  要求计算所能获得的邮资最大范围。即求最大值MAX,使在1—MAX之间的每一个邮票资值都得到。
  例如,N=4,有2种邮票,面值分别为1分、4分,于是可以得到1—10分和12分、13分、16分邮资,由于得不到11分和15分,所以邮资的最大值范围为10。

输入格式:

  输入文件stamps.in中读入数据,该文件第1行为最多粘贴的邮票张数N,第2行为邮票种数M,以下M行各有一个数字,表示邮票的面值Xi。

输出格式:

  输出文件stamps.out:
  1、若最大范围为空,则输出0
  2、若最大范围不为空,则把结果输出到文件中。

输入样例#1:

4
2
1

输出样例#1

10

【解题分析】

暴力枚举,从面值1开始枚举所有的面值可能,如果某个面值不能出现,则它的前一个面值是最小面值。

如何判定一个面值是否存在呢?如果一个面值存在,那它的邮票数量必然少于n,方案可能不唯一,基于贪心的原则,我们可以记录面值为S的时候需要的最少的邮票数量,设d[i]表示面值为i的需要的最少邮票数,基于加法原理,我们可以对邮票数进行拆分,枚举所有可能d[i]=min{d[i-j]+d[j]},当d[i]无法求取就是断层点了。

显然,对于每一种邮票的面值,d[x]=1就是最小的邮票数,其他面值则预设无穷大即可。

【参考代码】

#include<iostream>
using namespace std;
int d[25505],n,m,x;
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>x;
		d[x]=1;  //单枚邮票面值
	}
	for(int i=1;i<=25500;i++){
		if(d[i]==0) d[i]=1000;  //预设无穷大
		for(int j=1;j*2<i;j++)
            d[i]=min(d[i],d[i-j]+d[j]);
		if(d[i]>n){
			cout<<i-1;
			return 0;
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值