贵州信息技术教师培训day18(贪心)

文章介绍了贪心算法的基本思想,通过找零问题和活动选择问题两个实例展示了贪心算法的运用。在找零问题中,从最大面值的硬币开始找零以减少硬币数量;在活动选择问题中,按照活动结束时间排序以最大化活动数量。文章强调贪心算法并不总是能得到全局最优解,但对某些问题能提供有效解决方案。
摘要由CSDN通过智能技术生成

算法思想

贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解,因此贪心算法不是对所有问题都能得到全局最优解。
如果该问题从局部最优可以推出整体最优或者整体最优解的近似解,那么可以借助贪心算法实现。
步骤:首先将该问题分解为若干子问题,紧接着找出合适的贪心策略,求子问题的局部最优解,最终达到整体最优或者最优解的近似解。
【问题描述】超市有面值为1元、2元、5元的硬币,硬币数量不限。若他需要找零M元,问怎么找零才能使硬币数量最少?
【问题求解】如果要最少的硬币个数,则从面值最大的开始找零;当待找零金额大于该面值时,则计算需要多少个该面值的硬币;紧接根据剩余的金额,计算下一个面额所需要的数量;
最终待找零金额等于0则找零结束。
【程序设计】
1、添加头文件;
2、定义变量保存面额的数量;
3、定义数组保存不同面额;
4、定义数组保存不同面额找零的数目;
5、定义主函数;
6、输入获取待找零金额;
7、从最大面额开始到最小面额,所以要使用For循环结构;
8、循环结构设计:会先计算需要几个当前最大面额(求
商)以及剩余所需要找零的金额(求余),再进行下一个
面额;
9、最后输出所需要的面额。

#include <bits/stdc++.h>
using namespace std;
const int maxn=3;
int ans[maxn];//每个面值支付的数目
int coin[]= {1,2,5};//面值
int main() {
int money;//待支付金额
cin>>money;
for(int i=maxn-1; i>=0; i--) {//从最大面值开始
     ans[i]=money/coin[i];//对应面值个数
     money=money-ans[i]*coin[i];//剩余金额
}
for(int i=maxn-1; i>=0; i--) {//输出对应数目
cout<<coin[i]<<":"<<ans[i]<<endl;
}
return 0;
}

是不是所有最少硬币问题都可
以用贪心法???
eg:7,6,1
支付12
最少硬币问题能否使用贪心法,跟硬币的面值有关。在给
定的硬币面值中,若任一面值的硬币,大于比它面值小的
硬币的面值和,便可以使用贪心法。
(例:1,5,11取15)。

【问题描述】假设你在贵阳花溪十里河滩有1个烧烤炉出租,当天有
一批游客已经确定了需要租赁的时间段下了订单,每个订单的金额都一
样,怎么选择预订的订单可以使受益最大?
求一种最优的安排方案,使得所有安排的订单数最多。
【怎么选择贪心策略】
按照最早开始的时间:
1-3,3-9,4-7,7-11
按照所需要的最短时间:
1-2,6-9,4-8,8-13
按照结束的最早时间:
1-3,3-9,4-7,7-11 或者 1-2,6-9,4-8,8-13 在这里插入图片描述程序设计
1、添加头文件;
2、定义活动(结构体);
3、输入活动数目以及活动开始和结束时间;
4、确定策略;
5、按照活动结束时间排序;
6、如果当前活动结束时间低于下一个活动开始时间,安
排上,跟新为当前活动(for循环);
7、输出最终活动数目。

#include <bits/stdc++.h>
using namespace std;
struct meet{
int s,e;//开始和结束时间
}a[10000];
bool cmp(meet a,meet b){
return a.e<b.e;
}//返回先结束的
int main()
{
int n;    
cin>>n;
for(int i=0;i<n;i++){
scanf("%d%d",&a[i].start,&a[i].end);
}
 sort(a,a+n,cmp);//按照结束时间进行排序
int num=1;//至少安排一个活动
int LastTime=0;//保存当前活动的下标
for(int i=1;i<n;i++){
if(a[LastTime].end<a[i].start{//活动结束时间早于下一个开始时间
//一个开始时间
num++;//活动个数
LastTime=i;
}
}
cout<<num<<endl;
}  

【问题描述】设有n个正整数,将它们连接成一排,组成一个最大的多位整数。
例如:n=3时,3个整数13,312,343,连成的最大整数为34331213。
又如:n=4时,4个整数7,13,4,246,连成的最大整数为7424613。
输入:n
N个数
输出:连成的多位数
【问题求解】此题很容易想到使用贪心法,把整数转化为字符
串,然后按从大到小的顺序连接起来;测试题目的例子也都符
合,但最后测试的结果却不全对。
【问题分析】12,121应该组成12121而非12112,那么是不
是相互包含的时候就从小到大呢?也不一定,如12,123就是
12312而非12123,这种情况就有很多种了。是不是此题不能
用贪心法呢?
【问题求解】正确判断依据:先把整数转换成字符串,然后在
比较a+b和b+a,如果a+b>=b+a,就把a排在b的前面,反
之则把a排在b的后面。
【程序设计】
1、添加头文件;
2、定义字符数组存储输入的字符串;
3、定义待输入字符串的个数;
4、定义规则进行排序;
5、输出最终结果。

#include <bits/stdc++.h>
using namespace std;
string s[25]; 
bool cmp(string a,string b) {//string可以直接比较。
return a+b>b+a;
}
int main() {
int n;
cin>>n;
for(int i=0; i<n; i++) cin>>s[i];
sort(s,s+n,cmp);//贪心策略 
for(int i=0; i<n; i++) cout<<s[i];
return 0;
}

贪心算法概念及特点

Ø贪心算法(又称贪婪算法):在对问题求解时,总是做出在当前看
来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到
的是在某种意义上的局部最优解;
Ø只用考虑局部情况,算法思想比较简洁、直观,实现非常简单,复
杂度较低,效率较高

一本通 例 6.3 删数问题(Noip1994)

键盘输入一个高精度的正整数n(n<=1000位),去掉其中任意s个数字后剩下的数字按原左右顺序将组成一个新的正整数。编程对给定的n和s(s<n的位数,且数据保证n删除s个数之后不为0,还是一个非0的整数),寻找一种方案,使得剩下的数字组成的数最小。
例如:153748要删除2个数,使得剩下的数字最小,应当删除5和7,得到1348。(注意:1087如果要删除1个数,删除1结果是最小的,得到结果87)
【输入】
第一行是一个高精度整数n
第二行是需要删除的位数s
【输出】
最后剩下的最小数
【样例输入】
153748
2
【样例输出】
1348

//删数问题
#include<iostream>
#include<cstring>
using namespace std;

int main()
{
	string n;   //字符串,存放大数n
	int s;
	bool flag;
	cin>>n>>s;
	//递增区间删末尾字符,递减区间删除第一个
	size_t len = n.length();
	for(int i=1;i<=s;i++)
	{
		for(size_t j=0;j < len;j++)
		{
			if(n[j]>n[j+1]){//递减
				for(size_t k=j;k < len;k++)//向前移一个位置
					n[k]=n[k+1];
				break;
			}		
		}
		len--;
	}
	
	for(size_t i=0;i<len;i++){
		if(n[i]!='0') flag=true;
		if(flag) cout<<n[i];
	}
		
	return 0;
}

【ICPC/NOI】基础-活动选择

学校在最近几天有n(n<=100)个活动,这些活动都需要使用学校的大礼堂,在同一时间,礼堂只能被一个活动使。由于有些活动时间上有冲突,学校办公室人员只好让一些活动放弃使用礼堂而使用其他教室。
现在给出nn个活动使用礼堂的起始时间begini和结束时间endi​(begini​<endi​),请你帮助办公室人员安排一些活动来使用礼堂,要求安排的活动尽量多。请问最多可以安排多少活动?
请注意,开始时间和结束时间均指的是某个小时的0分0秒,如:3 5,指的是3:00~5:00,因此3 5和5 9这两个时间段不算冲突的时间段。
【输入】
第一行一个整数n(n<=100)
接下来的n行,每行两个整数,第一个begini​,第二个是endi​(begini​<endi​<=32767)
【输出】
输出最多能安排的活动数
【样例输入】

11
3 5
1 4
12 14
8 12
0 6
8 11
6 10
5 7
3 8
5 9
2 13

【样例输出】

4
#include<iostream>
#include<algorithm>
using namespace std;
const int MAX=100;

struct hd{
	int beginhTime;  
	int endhTime;    
}a[MAX];

bool cmp(hd a,hd b){
	return a.endhTime < b.endhTime;
}
int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
		cin>>a[i].beginhTime>>a[i].endhTime;
		
	sort(a,a+n,cmp);
	
	int num=1;
	int NextTime=0;
	for(int i=0;i<n;i++){
		if(a[NextTime].endhTime <= a[i].beginhTime){
			num++;
			NextTime=i;
		}
	}
	cout<<num<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值