浅析C语言贪心算法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

贪心算法的定义:
贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
解题的一般步骤是:
1.建立数学模型来描述问题;
2.把求解的问题分成若干个子问题;
3.对每一子问题求解,得到子问题的局部最优解;
4.把子问题的局部最优解合成原来问题的一个解。
如果大家比较了解动态规划,就会发现它们之间的相似之处。最优解问题大部分都可以拆分成一个个的子问题,把解空间的遍历视作对子问题树的遍历,则以某种形式对树整个的遍历一遍就可以求出最优解,大部分情况下这是不可行的。贪心算法和动态规划本质上是对子问题树的一种修剪,两种算法要求问题都具有的一个性质就是子问题最优性(组成最优解的每一个子问题的解,对于这个子问题本身肯定也是最优的)。动态规划方法代表了这一类问题的一般解法,我们自底向上构造子问题的解,对每一个子树的根,求出下面每一个叶子的值,并且以其中的最优值作为自身的值,其它的值舍弃。而贪心算法是动态规划方法的一个特例,可以证明每一个子树的根的值不取决于下面叶子的值,而只取决于当前问题的状况。换句话说,不需要知道一个节点所有子树的情况,就可以求出这个节点的值。由于贪心算法的这个特性,它对解空间树的遍历不需要自底向上,而只需要自根开始,选择最优的路,一直走到底就可以了。


提示:以下是本篇文章正文内容,下面案例可供参考

一、是什么?

贪心算法的定义:
贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

二、使用步骤

解题的一般步骤是:
1.建立数学模型来描述问题;
2.把求解的问题分成若干个子问题;
3.对每一子问题求解,得到子问题的局部最优解;
4.把子问题的局部最优解合成原来问题的一个解。

三、贪心算法案例

3.1背包问题:

先给大家介绍一下这个问题,就是给你一个背包,背包容量有限,但现在你要用这个背包去装一些物品,但这些物品价值不同,有的价值高,有的价值低,但我们想要尽可能的提升这个】背包的价值,所以我们要装一些价值更高的东西。

比如下面这个题:装满宝藏的藏宝洞。藏宝洞里面有 N(N≤100)N(N≤100) 堆金币,第 N堆金币的总重量和总价值分别是 x。有一个承重量为 N(N≤1000)T(T≤1000) 的背包,但并不一定有办法将全部的金币都装进去。他想装走尽可能多价值的金币。所有金币都可以随意分割,分割完的金币重量价值比(也就是单位价格)不变。请问最多可以拿走多少价值的金币?

 下面我给出这个题的代码:

#include<stdio.h>

struct stu {
	int weight;
	int price;
	double prices;
};


double tanxin(struct stu* arr, int N,int T) {
	double bag = T * 1.00;
	 double all_weight = 0.0,all_price=0.0;
	 double diff_weight = 0.0;
	for (int i = 0; i < N; i++) {
		all_weight += arr[i].weight;
		if (all_weight <= bag) {
			all_price += arr[i].price;
		}
		 if(all_weight > bag) {
			 diff_weight = arr[i].weight-(all_weight-bag);
			all_price += diff_weight / arr[i].weight * arr[i].price;
			break;
		
		}
	}
	return all_price;
}
int main()
{
	int N, T;
	scanf("%d%d", &N, &T);
	struct stu arr[10000] = {0};
	
	for (int i = 0; i < N; i++) {
		scanf("%d%d", &arr[i].weight,&arr[i].price);
	}

	for (int i = 0; i < N; i++) {
		arr[i].prices = arr[i].price*1.00 / arr[i].weight;
	}
	
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N - 1 - i; j++) {
			if (arr[j].prices< arr[j+1].prices) {
				struct stu temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}

	
	double all_price = tanxin(arr, N,T);

	printf("%.2lf\n", all_price);

	return 0;
}

 3.2活动选择问题

这个问题就是我们要去参加几个活动,但是这几个活动在时间上可能会发生冲突,所以我们要尽可能的多参加,这时就可以用贪心算法来求最多可以参加多少个活动。

例如下面这道题(例子来自洛谷)

 下面是这道题的代码:

#include<stdio.h>
#include<stdlib.h>

struct stu {
	int begin;
	int finish;
};

int cmp(const void* a, const void* b) {
	struct stu* s1 = (struct stu*)a;
	struct stu* s2 = (struct stu*)b;
	if (s1->finish < s2->finish)
		return -1;
	else if (s1->finish > s2->finish)
		return 1;
	else
		return 0;
}


int main()
{
	int n = 0;
	scanf("%d", &n);
	struct stu *arr = (struct stu*)malloc(n * sizeof(struct stu));
	for (int i = 0; i < n; i++) {
		scanf("%d%d", &arr[i].begin, &arr[i].finish);
	}

	qsort(arr, n, sizeof(struct stu), cmp);

	int count = 1;
	int i = 0; int k = 1;
	while (k<n) {
		if (arr[i].finish <= arr[k].begin) {
			count++;
			i++;
			arr[i].finish = arr[k].finish;
			k++;
		}
		else {
			k++;
		}
	}

	printf("%d\n", count);

	free(arr);
	arr = NULL;
	return 0;
}

大家可以简单看一下这两道题。 

 

 


 

总结

这篇文章我简单介绍了贪心算法,真的只是简单介绍,大佬们可以划走了,但这篇文章对新手还是会有很多帮助的,希望这篇文章可以为广大算法新手们的深入学习打好基础。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值