145
社区成员
发帖
与我相关
我的任务
分享目录
二、以{0-1}背包问题和背包问题为例,讨论动态规划算法与贪心算法的异同
3.1完成教材114页算法实现题4-2,总结实验出现问题及解决方法
3.2完成教材118页算法实现题4-14,总结实验出现问题及解决方法
(1)贪心算法的概念:
贪心算法是通过一系列选择来得到问题的解,所做的每个选择都是当前状态下局部最好选择,即贪心选择。这种启发式的策略并不总能奏效,但在许多情况下确能达到预期目的。
(2)贪心选择性质:
所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每步所做的贪心选择最终导致问题的整体最优解,通常可以用类似于证明活动安排问题的贪心选择性质时所采用的方法来证明。首先考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始。做了贪心选择后,原问题简化为规模更小的类似子问题。然后用数学归纳法证明,通过每一步做贪心选择,最终可得到问题的整体最优解。其中,证明贪心选择后的问题简化为规模更小的类似子问题的关键在于,利用该问题的最优子结构性质。
(3)贪心算法的求解步骤:
1)按照贪心选择策略对数据进行预处理;
2)从问题初始状态开始;
3)采用循环语句,向求解目标前进一步,根据局部最优策略,贪心的得到一个部分解,缩小问题范围或规模;
4)将所有部分解综合起来,得到问题的最终解。
本章学习了贪心算法的一些相关原理与思想,也从背包问题中体会到动态规划算法与贪心算法之间的一些异同点。结合0-1背包问题和背包问题对贪心算法和动态规划算法进行了区分。
动态规划的两个基本要素:1,最优子结构性质 2.重叠子问题
贪心算法的两个基本要素:1.最优子结构性质 2.贪心选择
都要求问题具有最优子结构性质。
在动态规划算法中,每步所做的选择往往依赖于相关子问题的解。因而只有在解出相关子问题后,才能做出选择。而在贪心算法中,仅在当前状态下做出最好选择,即局部最优选择。再去解做出这个选择后产生的相应的子问题。贪心算法所做的贪心选择可以依赖以往所做过的选择,但决不依赖将来所做的选择,也不依赖子问题的解。正是由于这种差别,动态规划算法通常以自底向上的方式解各子问题,贪心算法则通常以自顶向下的方式进行,以迭代的方式做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为规模更小的子问题。

代码:
#include<stdio.h>
#include<stdlib.h>
int up(const void* a, const void* b)
{
return *(int*)a - *(int*)b;
}
int down(const void* a, const void* b)
{
return *(int*)b - *(int*)a;
}
int getMin(int* a, int n)
{
int min = 0;
for (int i = 0; i < n - 1; i++)
{
qsort(a + i, n-i,sizeof(int),&up);
a[i + 1] += a[i];
min += a[i + 1] - 1;
}
return min;
}
int getMax(int* b, int n)
{
int max = 0;
for (int i = 0; i < n - 1; i++)
{
qsort(b + i, n - 1, sizeof(int), &down);
b[i + 1] += b[i];
max += b[i + 1] - 1;
}
return max;
}
int main()
{
int a[100], b[100];
int n;
FILE *file_in = fopen("input.txt","r");
fscanf(file_in,"%d", &n);
for (int i = 0; i < n; i++)
{
fscanf(file_in,"%d", &a[i]);
b[i] = a[i];
}
fclose(file_in);
int min = getMin(a, n);
int max = getMax(b, n);
FILE *file_out = fopen("output.txt","w");
fprintf(file_out, "%d %d", max, min);
fclose(file_out);
return 0;
}

代码:
#include<queue>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
ll a[100005];
int main() {
int n, k;
cin >> n >> k;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
priority_queue<ll, vector<ll>, greater<ll> >p;
priority_queue<ll, vector<ll>, less<ll> >q;
for (int i = 0; i < n; i++) {
p.push(a[i]);
q.push(a[i]);
}
int m = n;
while (m > k) {
m = m - k + 1;
}
for (int i = 0; i < k - m; i++) {
p.push(0);
}
ll minsum = 0;
while (p.size() > 1) {
ll sum = 0;
for (int j = 0; j < k; j++) {
if (!p.empty()) {
sum += p.top();
p.pop();
}
}
p.push(sum);
minsum += sum;
}
ll maxsum = 0;
while (q.size() > 1) {
ll sum = 0;
for (int j = 0; j < 2; j++) {
if (!q.empty()) {
sum += q.top();
q.pop();
}
}
q.push(sum);
maxsum += sum;
}
cout << maxsum << " " << minsum << endl;
return 0;
}