145
社区成员
发帖
与我相关
我的任务
分享目录
二、算法实验1:完成教材114页算法实现题4-2,总结实验出现问题及解决方法。
三、算法实验2:完成教材118页算法实现题4-14,总结实验出现问题及解决方法。
(1)最优子结构性质:一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质,也称此问题满足最优性原理。
(2)贪心选择性质:贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择(贪心选择)得到。
共同点:贪心算法和动态规划算法都要求问题具有最优子结构性质
不同点:①动态规划通常以递推方式求解各个子问题,某个问题的解依赖于已知子问题的解再做出选择。
②贪心算法依赖于一系列的局部贪心选择和求解每个局部阶段先做贪心选择再解子问题。
①活动安排问题
如何安排n个活动,令最多的活动使用资源?即如何高效地安排最多的活动使用某一公共资源?
【例】11个活动的开始时间和结束时间按结束时间的非减序排列如下:

求活动安排。

②背包问题
与0-1背包问题相似,不同的是,在选择物品i装入背包时,可以选择物品i的一部分,而不一定全部装入背包,
。
这两类问题都具有最优子结构性质,极为相似,但背包问题可用贪心算法求解得到最优解,0-1背包问题却不能用贪心算法求解。
字符的二进制编码方式:
哈夫曼编码:数据文件压缩的编码方法。其压缩率通常在20%~90%之间。

【例】

解:求以频率为权值的哈夫曼树,其中
。构造的哈夫曼树如图所示。

Dijkstra算法

①Prime算法
②Kruskal算法

最优合并问题:给定k个排好序的序列,用2路合并算法将这k个序列合并成一个序列。假设采用的2路合并算法合并2个长度分别为m和n的序列需要m+n-1次比较。试设计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。
#include<bits/stdc++.h>
using namespace std;
bool cmp(int a,int b) {
return a>b;
}
int MaxMerge(int a[],int k) {
int max=0;
for(int i=0; i<k-1; i++) {
sort(a+i,a+k,cmp);
a[i+1]=a[i]+a[i+1];
max=max+a[i+1]-1;
}
return max;
}
int MinMerge(int b[],int k) {
int min=0;
for(int i=0; i<k-1; i++) {
sort(b+i,b+k);//升序排列
b[i+1]=b[i]+b[i+1];
min=min+b[i+1]-1;
}
return min;
}
int main() {
int k;
cin>>k;
int a[k],b[k];
int x;
for(int i=0; i<k; i++) {
cin>>x;
a[i]=x;
b[i]=x;
}
cout<<MaxMerge(a,k)<<" "<<MinMerge(b,k)<<endl;
return 0;
}
时间复杂度:
最少比较次数:O(nlogn)
最多比较次数:O(n)
空间复杂度:O(n)
多元Huffman编码问题:在一个操场的四周摆放着n堆石子。现要将石子有次序地合并成一堆。规定每次至少选2堆,最多选k堆石子合并成新的一堆,合并的费用为新的一堆的石子数。试设计一个算法,计算出将n堆石子合并成一堆的最大总费用和最小总费用。
#include <iostream>
#include <queue>///队列库函数
using namespace std;
long long int max_sum;
long long int min_sum;
priority_queue <int, vector<int>, less<int> > q1;
priority_queue <int, vector<int>, greater<int> > q2;
void get_maxsum();
void get_minsum(int);
int main()
{
int n, k, x;
cin >> n >> k;
for(int i = 0; i < n; i++)
{
cin >> x;
q1.push(x);
q2.push(x);
}
max_sum = min_sum = 0;
get_maxsum();
// cout << "----------" << endl;
get_minsum(k);
// cout << "----------" << endl;
cout << max_sum << " " << min_sum << endl;
return 0;
}
void get_maxsum()
{
long long sum = 0;
// cout << "q1.size = " << q1.size() << endl;
while((int)q1.size() >= 2)
{
sum = 0;
for(int i = 0; i < 2; i++)
{
sum += q1.top();
q1.pop();
}
q1.push(sum);
max_sum += sum;
// cout << "q1.size = " << q1.size() << endl;
}
}
void get_minsum(int k)
{
long long sum = 0;
while(q2.size() % (k-1) != 1)
{
q2.push(0);
}
// cout << "q2.size = " << q2.size() << endl;
while((int)q2.size() >= k)
{
sum = 0;
for(int i = 0; i < k; i++)
{
sum += q2.top();
q2.pop();
}
q2.push(sum);
min_sum += sum;
// cout << "q2.size = " << q2.size() << endl;
}
}