购物(贪心)

原题链接
题目描述

你就要去购物了,现在你手上有N种不同面值的硬币,每种硬币有无限多个。为了方便购物,你希望带尽量少的硬币,但要能组合出1到X之间的任意值。

输入格式
第一行两个数X、N,以下N个数,表示每种硬币的面值。

输出格式
最少需要携带的硬币个数,如果无解输出-1.

样例输入
20 4
1 2 5 10

输出
5

【数据规模】
对于30%的数据,满足N≤3,X≤20;
对于100%的数据,满足N≤10,X≤1000.

起初没想到是贪心,用深搜做的,wa了好几次…还一个就是受之前做过的一道题的影响,总觉得思路差不多,谁知全然不同…

思路:先将所有的面值按升序排列,之后从1开始往上枚举,如果现在的钱数不够了,就加上一个能加的(面值小于等于当前所需钱数)最大面值。注意是最大面值。这样就能保证该面值钱数能用尽可能多的时间。还一个要注意的是,如果排过序的面值最小不是1,那肯定无解,比如最小是2,那么1就无法表示。

code:

#include<bits/stdc++.h>
using namespace std;
int x,n,a[12],cnt,sum;
int main(){
	cin>>x>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	sort(a+1,a+n+1);
	if(a[1]!=1){
		cout<<-1;
		return 0;
	}
	int j=0,i=0,k;	//i表示当前的钱数,j表示指向的面值。
	while(i<x)
	{
		i++;
		if(j+1<=n&&a[j+1]<=i&&sum<i)	//当前的钱数比后面一个的面值大且当前所拥有的不够用
		{
			for(k=j+1;k<=n;k++){	//往后寻找比当前钱数小的最大面值
				if(a[k]>i) break;
			}
			j=k-1,sum+=a[j],cnt++;
		 } 
		else if(sum<i) sum+=a[j],cnt++;	//否则,就加上最大的能加的
		//cout<<i<<" "<<sum<<" "<<cnt<<endl;
	}
	cout<<cnt;
	return 0;
} 

今天比赛做到两个贪心题,思考的时间都不短,得专题训练!

如果有哪里不对或者不懂的地方欢迎留言评论哦!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值