1. 程式人生 > >dp - 活動選擇問題

dp - 活動選擇問題

需要 我們 思考 方法 end problem ctp 時間復雜度 ble

  活動選擇問題是一類任務調度的問題,目標是選出一個最大的互相兼容的活動集合。例如:學校教室的安排問題,幾個班級需要在同一天使用同一間教室,但其中一些班級的使用時間產生沖突,一些班級的時間是兼容的,我們需要找出最大的相互兼容的這樣一個集合。實際上,運用‘貪心’的思想,可以準確又效率的找出這樣一個集合,但為了練習一下動態規劃,這篇使用了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)。

dp - 活動選擇問題