赞
踩
提示:这里可以添加本文要记录的大概内容:
对几个互相竞争的活动进行调度,它们都要求以独占的方式使用某一公共资 源。而在同一时间内只有一个活动能使用这一资源。假设有一个需要使用某一资源的 n 个活动组成的集合 S={a1,a2,a3,…,an}。每个活动 ai 都有一个要求使用该资源的起始时间 si 和一个结束时间 fi,且 si <fi。如果选择了活动 i,则它在半开时间区间[si, fi)内占用资源。若区间[si, fi)与区间[sj, fj)不相交,则称活动 i 与活动 j 是兼容的。
活动选择问题就是要选择出一个由互不兼容的问题组成的最大子集合
动态规划是贪心算法的基础。
贪心算法即通过做一系列的选择来给出某一问题的最优解。对算法中的每一个决策点,做一个当时最佳的选择。贪心算法的使用条件:贪心选择性质和最优子结构是两个关键的特点。如果我们能够证明问题具有这些性质,那么就可以设计出它的一个贪心算法。
贪心算法的基本思路:
实现一个任务调度问题(课本 P241):在单处理器上具有期限和惩罚的单位时间任务调度
- 实现这个问题的贪心算法,并写出流程图或者伪代码。
- 将每个 Wi 替换为 max{W1,W2……Wn}-Wi 运行算法、比较并分析结果
实例截图为:
代码如下:
#include <iostream> #include <algorithm> #include <string> #include <vector> using namespace std; int main(){ int n; cout << "请输入任务个数" << endl; cin >> n; vector<int> test(n,0); vector<int> d(n,0); vector<int> w(n,0); vector<int> visited(n,0); long result = 0; cout << "请输入每个任务的截止时间" << endl; for(int i = 0;i < n;i++){ cin >> d[i]; } cout << "请输入每个任务的惩罚" << endl; for(int i = 0;i < n;i++){ cin >> w[i]; } for(int i = 0;i < n - 1;i++){ for(int j = 0;j < n - 1;j++){ if(w[j] < w[j+1]){ swap(d[j],d[j+1]); swap(w[j],w[j+1]); } } } for(int i = 0;i < n;i++){ bool flag = false; for(int j = d[i];j > 0;j--){ if(!visited[j - 1]){ visited[j - 1] = true; flag = true; break; } } if(!flag){ cout << "放弃的任务截止时间为" << d[i] << "超市代价为" << w[i] << endl; result += w[i]; } } cout << result << endl; return 0; }
如代码所示,主要思想就是根据惩罚时间的大小使用冒泡排序进行排序可以用其他排序方式进行优化,但由于后续选择任务调度的代码复杂度为O(n^2),因此不会提升整个代码的时间复杂度
,然后按顺序决定是否选择任务来调度,实现最小化延迟任务的惩罚之和。(每个任务都执行单位时间,因此看任务集中截止时间小于等于t的任务数是否小于等于t,判断是否可以调度该任务)。
输入书上的实例,得到该程序代码的输入输出截图如下图所示:
输入输出结果正确。
代码如下即稍微改动一下即可
:
#include <iostream> #include <algorithm> #include <string> #include <vector> using namespace std; int main(){ int n; cout << "请输入任务个数" << endl; cin >> n; vector<int> test(n,0); vector<int> d(n,0); vector<int> w(n,0); vector<int> visited(n,0); long result = 0; cout << "请输入每个任务的截止时间" << endl; for(int i = 0;i < n;i++){ cin >> d[i]; } cout << "请输入每个任务的惩罚" << endl; for(int i = 0;i < n;i++){ cin >> w[i]; } for(int i = 0;i < n - 1;i++){ for(int j = 0;j < n - 1;j++){ if(w[j] < w[j+1]){ swap(d[j],d[j+1]); swap(w[j],w[j+1]); } } } for(int i = 0;i < n;i++){ bool flag = false; for(int j = d[i];j > 0;j--){ if(!visited[j - 1]){ visited[j - 1] = true; flag = true; break; } } if(!flag){ cout << "放弃的任务截止时间为" << d[i] << "超市代价为" << w[i] << endl; result += w[i]; } } cout << result << endl; return 0; }
该程序的输入输出截图如图所示:
进行分析后,分析过程如图所示:
发现结果正确
以上两段代码,时间复杂度均为O(n^2)n为任务数
,空间复杂度为O(n)
通过对任务调度问题使用贪心算法进行实现,加深了我对于贪心算法的理解和实践。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。