贪心算法示例

每一步都是局部最优,但是不一定是整体最优,一般是近似解

1.找零问题   成立

2.石子合并问题   部分不成立

一、找零问题:

25/10/5/1  这四种币额去凑出48美元,使给出的硬币数量最少

第一步,可以给出4种面额中的任何硬币,贪心算法会选择一个25的硬币,因为它能把余下的数量降到最低,剩余23美分;

第二步,最佳选择是10美元硬币,能把余下的数量降到最低,剩余13美分;

第四步,同理,选择10美元硬币,剩余3美分;

第五步:没得选了,三个1美元硬币;

举例:

设有50、20、10、5、1、0.5、0.1等面额的零钱,顾客购物花费n元,在支付(int)(n / 100 + 1) * 100元后,收银员应如何找零,才能使找回的钱数最少

输入:n,表示顾客所花的钱数,最多包含一位小数。

输出:找回的零钱数。

样例输入1:67.5

样例输出1:5

样例输入2:243

样例输出2:4

代码一:方便理解,思路清晰明了

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<math.h>

using namespace std;

int main()
{
	double realspend;
    (void)scanf("%lf", &realspend);
	int spend = realspend * 10;
	int leave = ((int)(spend / 1000) + 1) * 1000 - spend;
	int i = 0;
	while (leave >= 500)
	{
		leave = leave - 500;
		i++;
	}
	while (leave >= 200 && leave < 500)
	{
		leave = leave - 200;
		i++;
	}
	while (leave >= 100 && leave < 200)
	{
		leave = leave - 100;
		i++;
	}
	while (leave >= 50 && leave < 100)
	{
		leave = leave - 50;
		i++;
	}
	while (leave >= 10 && leave < 50)
	{
		leave = leave - 10;
		i++;
	}
	while (leave >= 5 && leave < 10)
	{
		leave = leave - 5;
		i++;
	}
	while (leave >= 1 && leave < 5)
	{
		leave = leave - 1;
		i++;
	}
	printf("%d", i);
	return 0;
}

代码二:“炫技代码”,华而不实

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>

using namespace std;

int TanxinZhaoLing(int leave, int* yingbi)
{
	int zhangshu=0;
	for (int i = 0; leave != 0; i++)
	{
		if (leave < yingbi[i])
			continue;
		leave = leave - yingbi[i];
		zhangshu++;
		i--;
	}
	return zhangshu;
}

int main()
{
	double spend;
	(void)scanf("%lf", &spend);
	spend = spend * 10;
	int a[7] = {500,200,100,50,10,5,1};
	int leave = ((int)(spend / 1000) + 1) * 1000 - spend;
	int zhangshu = TanxinZhaoLing(leave, a);
	printf("%d", zhangshu);
	return 0;
}

二、活动安排问题

有n个活动,E={1,2,3...},其中每个活动都要求使用同一资源,同一时间内只有一个活动能使用这一资源,每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si<fi。如果选择了活动i,则它在半开区间(si,fi)内占用资源,如果(si,fi)和(sj,fj)区间不相交,则称活动i和活动j是相容的,也就是说,si>=fj,或sj>=fi时,活动i和活动j相容。活动安排问题就是要在所给的集合中选出最大的相容活动子集合

求解思路:尽量选择结束时间早的活动:将活动按照结束时间大小进行排序,然后用i代表第i个活动,s[i]代表第i个活动开始时间,f[i]代表第i个活动结束时间

布尔型(bool)变量的值只有 真 (true) 和假 (false)

布尔型运算结果常用于条件语句

#include<stdio.h>
#include<iostream>

using namespace std;

//选择函数,输入项目个数,开始时间,结束时间,布尔类型的值
void GreedyChoose(int len, int* startTime, int* endTime, bool* mark)
{
	mark[0] = true;  //第一个活动一定安排

	int j = 0;  
	for (int i = 1; i < len; i++)
	{
		if (startTime[i] >= endTime[j])  //从第二个项目开始找开始时间大于前一个结束时间的活动
		{
			mark[i] = true;  //布尔类型,满足条件就true
			j = i;  //更改成最后一个安排的活动
		}
	}
}
int main()
{
	int startTime[11] = {1,2,0,5,3,5,6,8,8,2,12};  //开始的时间
	int endTime[11] = { 4,5,6,7,8,9,10,11,12,13,14 };  //结束的时间
	bool mark[11] = {false};
	//如果选择某个活动,则数组mark对应位置为true,否则为false
	GreedyChoose(11, startTime, endTime, mark);

	cout << "NO.\t" << "sTime\t" << "eTime\t" << endl;
	for (int i = 0; i < 11; i++)
	{
		if (mark[i])
		{
			cout << i + 1 << "\t" << startTime[i] << "\t" << endTime[i] << endl;
		}  //输出结果
	}
	return 0;
}

三、马踏棋盘算法

基本解法:深度优先搜索

从某位置出发,先试探下一个可能位置;进入一个新位置后就从该位置进一步试探下一个位置,若遇到不可行位置则退回一步;再试探其他位置

8*8数组chess[][]存储棋子周游状态,未走过位置赋值0,走过的位置依次为1,2,3,4

(x,y)为当前位置,j为当前第几步

辅助算法:贪心算法

在选择下一跳的位置时,总是先选择出口少的那个位置:

如果优先选择出口多的子结点,那么出口少的子结点会越来越多,很可能出现走不通的死结点,回退搜索浪费时间

四、数字组合问题:设有N个正整数,需要设计一个程序,使他们链接在一起成为最大的数字

冒泡排序

每次循环都会把最大的移动到最后面

for (int i = 0; i < 9; i++)  //外循环表示循环多少次(n个数:n-1)
{
	for (int j = 0; j <= 10- 1 - i; j++)  //内循环表示比较的数据
	{                    //10-1是下标
		if (array[j] > array[j + 1])
		{
			int temp = array[j];
			array[j] = array[j + 1];
			array[j + 1] = temp;
		}
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

挣钱钱暴富富

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值