转载---贪心算法

转载博主

1.贪心算法简介

1.1 基本定义

在贪婪算法(greedy method) 中,我们要逐步构造一个最优解。每一步,我们都在一定的标准下,做出一个最优决策。做出决策所依据的标准称为贪心准则(greedy criterion)。

贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。
也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。

贪心算法每一步必须满足以下条件:
  1、可行的:即它必须满足问题的约束。
  2、局部最优:他是当前步骤中所有可行选择中最佳的局部选择。
  3、不可更改:即选择一旦做出,在算法的后面步骤就不可改变了。

注意:!!!
贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。

1.2 贪心算法案例

钱币找零问题
假设1元、2元、5元、10元、20元、50元、100元的纸币分别有c0, c1, c2, c3, c4, c5, c6张。现在要用这些钱来找给顾客K元,怎么用数目最少的钱来找零?

贪心准则:在不超过要找的零钱总数的条件下,每一次都选择面值尽可能大的纸币,直到凑成的零钱总数等于要找的零钱总数。

#include

using namespace std;

int min(int a, int b) {
return a < b ? a : b;
}
int main()
{
//人民币面值集合
int values[] = { 1, 2, 5, 10, 20, 50, 100 };
//各种面值对应数量集合
int counts[] = { 3, 1, 2, 1, 1, 3, 5 };
//求442元人民币需各种面值多少张
//用来记录需要的各种面值张数
int money = 442;
int len = sizeof(values) / sizeof(values[0]);
int* result = new int[len];
for (int i = len - 1; i >= 0; i–) {
int num = 0; //当前面值纸币的数量
num = min(money / values[i], counts[i]); //当前纸币可以找的最大数量
money = money - num*values[i];
result[i] = num;
}
//输出最后结果
for (int i = 0; i < len; i++) {
if(result[i])
cout << “需要面额为” << values[i] << “的人名币” << result[i] << “张\n”;
}
cout << endl;

system("pause");
return 0;

}

程序结果:

需要面额为2的人名币1张
需要面额为5的人名币2张
需要面额为10的人名币1张
需要面额为20的人名币1张
需要面额为100的人名币4张

可以得出,求出的结果为最优解,但是,当纸币面值和数量为某些特殊情况下,贪心算法就无法给出最优解。但是,贪心算法往往能给出近似解,对于我们来说也是有价值的。

比如对于纸币有1、5、7面值的若干,要凑出10元
贪心解[3,0,1]
最优解[0,2,0]

1.3.贪心算法的基本思路

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

2.贪心算法最优性证明

2.1 贪心算法的前提

贪心策略适用的前提是:局部最优策略能导致产生全局最优解。
关键是贪心策略的选择,而贪心算法与动态规划的主要区别是:
贪心选择是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。即贪心选择是采用从顶向下、以迭代的方法做出相继选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题。
所以,贪心算法的正确性可以通过数学归纳法或贪心交换来给予证明。

2.2 最优子结构

当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。
运用贪心策略在每一次转化时都取得了最优解。问题的最优子结构性质是该问题可用贪心算法或动态规划算法求解的关键特征。

2.3 贪心算法与动态规划的区别

贪心算法的每一次操作都对结果产生直接影响,而动态规划则不是。
贪心算法对每个子问题的解决方案都做出选择,不能回退;动态规划则会根据以前的选择结果对当前进行选择,有回退功能。
能用贪心解决的问题,也可以用动态规划解决
3.贪心算法的经典问题

3.1 近似解

0/1背包问题
3.2 最优解

拓扑排序
单源最短路径(Dijkstra算法)
最小生成树(Kruskal算法、Prim算法)
连续背包问题

### 回答1: 好的,我可以帮您解决使用C语言编写转载问题的代码。 以下是一个使用C语言编写的简单程序,它可以将十进制数转换为任意进制(2到16进制): ```c #include <stdio.h> void convert(int num, int base) { int rem = num % base; if(num == 0) { return; } convert(num / base, base); if(rem < 10) { printf("%d", rem); } else { printf("%c", rem - 10 + 'A'); } } int main() { int num, base; printf("请输入一个十进制数:"); scanf("%d", &num); printf("请输入您想要转换的进制:"); scanf("%d", &base); printf("转换结果为:"); convert(num, base); printf("\n"); return 0; } ``` 该程序中的`convert`函数递归地将十进制数转换为任意进制,并在转换过程中输出每一位数字或字母。 您可以使用该程序进行测试,并根据需要进行修改和调整。希望这可以帮助您解决您的问题! ### 回答2: 贪心算法是一种求解最优化问题的算法,通过每一步的贪心选择来达到全局最优解。对于求解转载问题,可以考虑使用贪心算法来解决。 首先,我们需要明确转载问题的具体要求。在转载问题中,假设有一组要转载的文章,每篇文章的阅读量和转载成本都不同。我们的目标是选择一部分文章进行转载,使得转载总阅读量最大,同时保持转载总成本不超过一个给定的阈值。 贪心算法的思路是每一步都选择当前局部最优解,从而达到全局最优解。在转载问题中,我们可以按照文章的阅读量进行排序,然后从大到小依次选择阅读量最大的文章进行转载,直到总成本超过给定的阈值或者所有文章都被转载完。 下面是使用C语言实现贪心算法求解转载问题的伪代码: ``` // 定义文章结构体 typedef struct { int id; int views; int cost; } Article; // 按照阅读量从大到小排序的比较函数 int compare_articles(const void* a, const void* b) { Article* article_a = (Article*)a; Article* article_b = (Article*)b; return article_b->views - article_a->views; } // 贪心算法求解转载问题的函数 void greedy_repost(Article articles[], int n, int max_cost) { // 按照阅读量从大到小排序文章数组 qsort(articles, n, sizeof(Article), compare_articles); int reposted_articles = 0; // 已转载的文章数量 int total_views = 0; // 总阅读量 int total_cost = 0; // 总成本 // 依次选择阅读量最大的文章进行转载,直到总成本超过阈值或者所有文章都被转载完 for (int i = 0; i < n; i++) { if (total_cost + articles[i].cost <= max_cost) { reposted_articles++; total_views += articles[i].views; total_cost += articles[i].cost; } } printf("已转载文章数量:%d\n", reposted_articles); printf("总阅读量:%d\n", total_views); } ``` 使用该贪心算法函数,我们可以传入文章数组、文章数量和阈值,得到最大总阅读量和已转载的文章数量。 注意:贪心算法的正确性依赖于问题的特性,不同的问题需要设计相应的贪心策略,有时贪心算法不能得到全局最优解。因此,在实际应用中,需要根据问题的具体情况进行分析和验证。 ### 回答3: 贪心算法是一种在每个步骤都做出局部最优选择的算法。对于转载问题,可以使用贪心算法来寻找最优解。 首先,我们需要定义问题的约束条件和目标函数。在转载问题中,假设有一系列的新闻文章,每篇文章有一个重要度和一个转载费用。我们的目标是选择一些文章进行转载,使得转载的总费用最小,但是仍能满足一定的重要度要求。 一种贪心算法的思路是,对于每一篇文章,我们计算其重要度与转载费用的比值。然后按照这个比值进行排序,选择比值最高的文章进行转载,直到满足重要度要求或者没有更多的文章可选为止。 以下是一个用C语言实现贪心算法求解转载问题的示例代码: ```c #include <stdio.h> #include <stdlib.h> // 定义文章结构体 typedef struct { int importance; int cost; double ratio; } Article; // 比较函数,用于排序 int compare(const void *a, const void *b) { Article *articleA = (Article*)a; Article *articleB = (Article*)b; if (articleA->ratio < articleB->ratio) { return 1; } else if (articleA->ratio > articleB->ratio) { return -1; } else { return 0; } } int main() { // 假设有6篇文章 Article articles[6] = { {10, 5, 0}, {5, 3, 0}, {8, 4, 0}, {15, 8, 0}, {7, 5, 0}, {6, 3, 0} }; // 计算每篇文章的比值 for (int i = 0; i < 6; i++) { articles[i].ratio = (double)articles[i].importance / articles[i].cost; } // 按照比值进行排序 qsort(articles, 6, sizeof(Article), compare); // 选择文章进行转载 int targetImportance = 20; int totalCost = 0; for (int i = 0; i < 6; i++) { if (targetImportance <= 0) { break; } if (articles[i].cost <= targetImportance) { targetImportance -= articles[i].cost; totalCost += articles[i].cost; } } printf("转载的总费用为:%d\n", totalCost); return 0; } ``` 以上代码首先定义了一个文章结构体,包含了重要度和转载费用两个属性,以及一个计算比值的字段。然后使用`qsort`函数对文章进行排序,按照比值从高到低的顺序排序。最后,使用贪心算法思想,从头开始选择文章进行转载,直到重要度要求不满足或者没有更多的文章可选为止。最后输出转载的总费用。 请注意,这个示例代码并非通用解决方案,而是一个示例,实际应用中需要根据具体需求进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值