IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 贪心专题讲解 -> 正文阅读

[数据结构与算法]贪心专题讲解

概述:

? ? ? ?贪心算法是指,在对问题求解时,总是以当前情况为基础作最优选择,而不考虑各种可能的整体情况,它所做出的仅仅是在某种意义上的局部最优解,省去了为找最优解要穷尽所有可能而必须耗费的大量时间,类似数学归纳法,无后效性,在运行过程中没有回溯过程,每一步都是当前的最佳选择。

? ? ? ? 难点是如何贪心和证明贪心的正确性,即如何用一个小规模的解构造更大规模的解,比赛过程中需要胆大心细地归纳、分析。

贪心的缺点:

  1. 可能得不到最优解
  2. 可能算不出答案

用贪心法求解需要满足以下特征:

  1. 最优子结构性质(当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质)
  2. 贪心选择性质

贪心常见问题

  1. 活动安排问题(区间调度问题)
  2. 区间覆盖问题
  3. 最优装载问题
  4. 多机调度问题

问题一

"Yakexi, this is the best age!" Dong MW works hard and get high pay, he has many 1 Jiao and 5 Jiao banknotes(纸币), some day he went to a bank and changes part of his money into 1 Yuan, 5 Yuan, 10 Yuan.(1 Yuan = 10 Jiao)
"Thanks to the best age, I can buy many things!" Now Dong MW has a book to buy, it costs P Jiao. He wonders how many banknotes at least,and how many banknotes at most he can use to buy this nice book. Dong MW is a bit strange, he doesn't like to get the change, that is, he will give the bookseller exactly P Jiao.

Input

T(T<=100) in the first line, indicating the case number.
T lines with 6 integers each:
P a1 a5 a10 a50 a100
ai means number of i-Jiao banknotes.
All integers are smaller than 1000000.

Output

Two integers A,B for each case, A is the fewest number of banknotes to buy the book exactly, and B is the largest number to buy exactly.If Dong MW can't buy the book with no change, output "-1 -1".

Sample Input

3
33 6 6 6 6 6
10 10 10 10 10 10
11 0 1 20 20 20

Sample Output

6 9
1 10
-1 -1

大致题意:?给定总钱数,一元,五元,十元,五十元,一百元的硬币的个数,求出使用最少和最多的硬币数。

思路:这是一个经典的贪心硬币问题,只需从大面值硬币开始选择,一直到最小面值的硬币,最后统计硬币的总数量,即为硬币的最少使用量。

硬币的最大使用量的求法则有些特殊,先求出总钱数与所有硬币总值的差值,再求出这部分差值使用硬币的最少数量,最后用总硬币数量减去差值使用硬币的最少数量,所得结果即为硬币的最多使用量。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<string.h>
#include<algorithm>
using namespace std;

int main() {
	int t;
	cin>>t;
	while(t--) {
		int mony,mony1=0;
		int a,b,c,d,e;
		int num=0;
		int num1=0;
		cin>>mony>>a>>b>>c>>d>>e;
		mony1=a*1+b*5+c*10+d*50+e*100-mony;
		int q=0;
		//最少
		if(mony>=100) {
			q=mony/100;
			if(q>=e) {
				q=e;
			}
			mony-=100*q;
			num+=q;
		}
		if(mony>=50) {
			q=mony/50;
			if(q>=d) {
				q=d;
			}
			mony-=50*q;
			num+=q;
		}
		if(mony>=10) {
			q=mony/10;
			if(q>=c) {
				q=c;
			}
			mony-=10*q;
			num+=q;
		}
		if(mony>=5) {
			q=mony/5;
			if(q>=b) {
				q=b;
			}
			mony-=5*q;
			num+=q;
		}
		if(mony>=1) {
			q=mony/1;
			if(q>=a) {
				q=a; 
			}
			mony-=1*q;
			num+=q;
		}
		if(mony==0) {
			cout<<num<<" ";
		} else {
			cout<<-1<<" ";
		}

		//最大
		if(mony1>=100) {
			q=mony1/100;
			if(q>=e) {
				q=e;
			}
			mony1-=100*q;
			num1+=q;
		}
		if(mony1>=50) {
			q=mony1/50;
			if(q>=d) {
				q=d;
			}
			mony1-=50*q;
			num1+=q;
		}
		if(mony1>=10) {
			q=mony1/10;
			if(q>=c) {
				q=c;
			}
			mony1-=10*q;
			num1+=q;
		}
		if(mony1>=5) {
			q=mony1/5;
			if(q>=b) {
				q=b;
			}
			mony1-=5*q;
			num1+=q;
		}
		if(mony1>=1) {
			q=mony1/1;
			if(q>=a) {
				q=a; 
			}
			mony1-=1*q;
			num1+=q;
		}
		if(mony1==0) {
			cout<<a+b+c+d+e-num1;
		} else {
			cout<<-1;
		}
		cout<<endl;
	}
	return 0;
}

问题二

电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。

Input

多组数据。对于每组数据:
第一行为正整数n,表示菜的数量。n<=1000。
第二行包括n个正整数,表示每种菜的价格。价格不超过50。
第三行包括一个正整数m,表示卡上的余额。m<=1000。

n=0表示数据结束。

Output

对于每组输入,输出一行,包含一个整数,表示卡上可能的最小余额。

Sample Input

1
50
5
10
1 2 3 2 1 1 2 3 2 1
50
0

Sample Output

-45
32

?思路:突破口:将菜的价格从小到大排序,对前n-1个物品进行DP,找出消费金额不超过m-5的方案中最大的消费金额sum,在此基础上,m - (sum+price[n]) 即为卡内最小余额。因此,我们DP应在余额为0~m-5之内找出最优的解。

这道题中需要用到DP,即动态规划,详细讲解参考b站《动态规划 硬币问题》

动态规划 硬币问题_哔哩哔哩_bilibili

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<string.h>
#include<algorithm>
using namespace std;

int num[1005];
int dp[1005];
int main() {
	int n;
	while(cin>>n) {
		if(n==0) {
			break;
		}
		for(int i=0; i<n; i++) {
			cin>>num[i];
		}
		memset(dp,0,sizeof(dp)); 
		sort(num+0,num+n);
		int mony;
		cin>>mony;
		if(mony<5) {
			cout<<mony<<endl;
		}else{
			for(int i=0;i<n-1;i++){
				for(int j=mony-5;j>=num[i];j--){
					//dp[j]=max(dp[j],dp[j-num[i]]+num[i]); 
					if(dp[j]<dp[j-num[i]]+num[i]){
						dp[j]=dp[j-num[i]]+num[i];
					}else{
						dp[j]=dp[j];
					}
				} 
			}
			cout<<mony-dp[mony-5]-num[n-1]<<endl;  
		} 
	}
	return 0;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-26 12:18:24  更:2021-07-26 12:20:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:45:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码