活动选择问题是一类任务调度的问题,目标是选出一个最大的互相兼容的活动集合。例如:学校教室的安排问题,几个班级需要在同一天使用同一间教室,但其中一些班级的使用时间产生冲突,一些班级的时间是兼容的,我们需要找出最大的相互兼容的这样一个集合。实际上,运用‘贪心’的思想,可以准确又效率的找出这样一个集合,但为了练习一下动态规划,这篇使用了dp的做法。
最优子结构以及递归公式书中给出了详细的分析过程,但课后练习题要求使用动态规划用代码实现算法,于是我就给出我的代码:
#include "stdafx.h" #include <iostream> #include <minmax.h> #include <vector> class DP { public: int ActivitySelectProblem(std::vector<int> & s, std::vector<int> & f) { std::vector<std::vector<int> > dp(s.size() - 1, std::vector<int>(s.size() - 1)); int count = 0; for (int l = 1; l < s.size(); l++) for (int i = 0; i < s.size() - l; i++) { int j = i + l - 1; dp[i][j] = 0; for (int k = i; k < j; k++) { if (f[i] <= s[k + 1]) dp[i][j] = max(dp[i][j], dp[i][k] + dp[k][j] + 1); count = max(count, dp[i][j] - 1); } } return count; } }; int main() { std::vector<int> s{ 1,3,0,5,3,5,6,8,8,2,12,17 }; std::vector<int> f{ 4,5,6,7,9,9,10,11,12,14,16,21 }; std::cout << DP().ActivitySelectProblem(s, f) << std::endl; getchar(); return 0; }
有递归公式,那么算法的实现是很简单的。为了简单,所以我使用返回集合的长度的方法,但实际上这是非常不显然的,看不出是哪些班级相互兼容,但我也没想到好办法实现保存合格的班级的下标,然后返回集合。我再思考思考。。。时间复杂度O(n^3)。