問題描述:
設有n個活動的集合e=,其中每個活動都要求使用同一資源,如演講會場等,而在同一時間內只有乙個活動能使用這一資源。每個活動i都有乙個要求使用該資源的起始時間si和乙個結束時間fi,且si 。
從圖中可以看出s中共有11個活動,最大的相互相容的活動子集為:和。
2、動態規劃解決過程
(1)活動選擇問題的最優子結構
定義子問題解空間sij是s的子集,其中的每個獲得都是互相相容的。即每個活動都是在ai結束之後開始,且在aj開始之前結束。
為了方便討論和後面的計算,新增兩個虛構活動a0和an+1,其中f0=0,sn+1=∞。
結論:當i≥j時,sij為空集。
如果活動按照結束時間單調遞增排序,子問題空間被用來從sij中選擇最大相容活動子集,其中0≤i<j≤n+1,所以其他的sij都是空集。
最優子結構為:假設sij的最優解aij包含活動ak,則對sik的解aik和skj的解akj必定是最優的。
通過乙個活動ak將問題分成兩個子問題,下面的公式可以計算出sij的解aij。
(2)乙個遞迴解
設c[i][j]為sij中最大相容子集中的活動數目,當sij為空集時,c[i][j]=0;當sij非空時,若ak在sij的最大相容子集中被使用,則則問題sik和skj的最大相容子集也被使用,故可得到c[i][j] = c[i][k]+c[k][j]+1。
當i≥j時,sij必定為空集,否則sij則需要根據上面提供的公式進行計算,如果找到乙個ak,則sij非空(此時滿足fi≤sk且fk≤sj),找不到這樣的ak,則sij為空集。
c[i][j]的完整計算公式如下所示:
親測**:
1 #include 2view code#define max_size 10010
3int
s[max_size];
4int
f[max_size];
5int
c[max_size][max_size];
6int
ret[max_size][max_size];78
using
namespace
std;910
void dp_selectof(int *s,int *f,int n,int c[max_size],int
ret[max_size])
1127}28
}29}30
}3132int
main()
3346
dp_selectof(s,f,n,c,ret);
47 printf("
最大子集的個數=%d\n
",c[1][n]+2
);48
return0;
49 }
下面是貪心法的**:
1 #include 2view code#define max_size 10010
3int
s[max_size];
4int
f[max_size];
5int
ret[max_size];
6int
c[max_size][max_size];
7using
namespace
std;89
void greedy_activity_selector(int *s,int *f,int n,int *ret)
1020}21
intmain()
2237
greedy_activity_selector(s,f,n,ret);
38for(i=0;i<=n;i++)
3943 printf("\n"
);44
}45 }
活動選擇問題 動態規劃 貪心演算法
問題描述 有乙個需要使用每個資源的n個活動組成的集合s 資源每次只能由乙個活動使用。每個活動ai都有乙個開始時間和結束時間,且 0 si fi 無窮 一旦被選擇後,活動ai就佔據半開時間區間 si,fi 如果 si,fi 和 sj,fj 互不重疊,則稱兩個活動是相容的。該問題就是要找出乙個由互相相容...
動態規劃 貪心演算法 活動選擇問題 收藏
問題描述和分析 演算法導論 p222 16.1活動選擇問題.這裡給出了動態規劃和貪心演算法兩種演算法的 view plaincopy to clipboardprint?動態規劃解法 include using namespace std const int n 11 int s n 2 int f...
活動選擇問題(動態規劃和貪心演算法)
有乙個由n個活動組成的集合s 1.這些活動使用同乙個資源,而這個資源在某一時刻只供乙個活動使用 2.每個活動都有乙個開始和結束時間si fi 如果被選中,則任務ai發生在半開時間區間 si,fi 3.如果兩個活動ai和aj不重疊,則稱兩個活動相容 活動選擇問題,希望選出乙個最大相容活動集 假設活動已...