有一个教室,而当天有多个活动,活动时间表如下:找出最大兼容活动集!活动已按结束时间升序排序.
采用动态规划需要满足两个条件:1.最优子结构2.子问题重叠
令
则c[i,j] = c[i,k]+c[k,j]+1;最后我们需要遍历所有可能的k值,找出最大的一个划分作为c[i,j],也即有子问题重叠问题。
即可以设计一个自底向上的算法,一步步到整个活动大小!
算法复杂度为O(
void Dynamic_Activity_Selector(int *s,int *f,int length) //动态规划算法
{
int c[13][13];
for (int m=0;m<12;m++) //初始化数组。当i>j时,c[i][j]为空集
{
for (int n=0;n<=m;n++)
{
c[n][m] = 0;
}
}
int imax=0;
for (int j=1;j<=length;j++) //自底向上填写表c[i][j]
{
for (int i=j-1;i>=0;i--)
{
for (int k=i+1;k<j;k++)
{
if (s[k]>=f[i] && f[k] <= s[j]) //检查划分点k是否满足条件
{
if (c[i][k]+c[k][j]+1 > c[i][j])
{
c[i][j] = c[i][k]+c[k][j]+1;
if (k > imax) //逐个输出 得到最大兼容子集
{
imax = k;
cout<<imax<<endl;
}
}
}
}
}
}
}
贪心算法的原理是在作出每个决策时,它在当时(局部)看来是最好的选择。作出一个贪心选择后,要求只剩下一个子问题。令
算法复杂度O(n)
迭代版本
void Greedy_Activity_Selector(int s[],int *f,int length) //迭代贪心算法
{
int *A = new int[length]; //存储最大兼容子集
if ( A == NULL)
return;
int i=0;
A[i++]=1;
int n=length;
int k=1;
for (int m=2;m<=n;m++)
{
if (s[m] >= f[k])
{
A[i++]=m;
k=m;
}
}
for(int j=0;j<i;j++)
cout<<A[j]<<endl;
delete []A;
}
/************************************************************************
CSDN 勿在浮沙筑高台
http://blog.csdn.net/luoshixian099
算法导论--贪心算法与动态规划(活动选择问题)
2015年6月18日
************************************************************************/
#include <iostream>
using namespace std;
void Recursive_Activity_Selector(int *s,int *f,int k,int n) //递归贪心算法
{
int m = k+1;
while ( (m<=n) && (s[m]<=f[k])) //选出满足活动的m
m++;
if (m <= n)
{
cout<<m<<endl;
Recursive_Activity_Selector(s,f,m,n);//递归
}
else
return;
}
void Greedy_Activity_Selector(int s[],int *f,int length) //迭代贪心算法
{
int *A = new int[length]; //存储最大兼容子集
if ( A == NULL)
return;
int i=0;
A[i++]=1;
int n=length;
int k=1;
for (int m=2;m<=n;m++)
{
if (s[m] >= f[k])
{
A[i++]=m;
k=m;
}
}
for(int j=0;j<i;j++)
cout<<A[j]<<endl;
delete []A;
}
void Dynamic_Activity_Selector(int *s,int *f,int length) //动态规划算法
{
int c[13][13];
for (int m=0;m<12;m++) //初始化数组。当i>j时,c[i][j]为空集
{
for (int n=0;n<=m;n++)
{
c[n][m] = 0;
}
}
int imax=0;
for (int j=1;j<=length;j++) //自底向上填写表c[i][j]
{
for (int i=j-1;i>=0;i--)
{
for (int k=i+1;k<j;k++)
{
if (s[k]>=f[i] && f[k] <= s[j]) //检查划分点k是否满足条件
{
if (c[i][k]+c[k][j]+1 > c[i][j])
{
c[i][j] = c[i][k]+c[k][j]+1;
if (k > imax) //逐个输出 得到最大兼容子集
{
imax = k;
cout<<imax<<endl;
}
}
}
}
}
}
}
int main()
{
int s[]={0,1,3,0,5,3,5,6,8,8,2,12,100}; //s[12]=100是为了动态规划的输出
int f[]={0,4,5,6,7,9,9,10,11,12,14,16,101};
int length = sizeof(s)/sizeof(s[0])-1;
cout<<"Recursive_Activity_Selector:"<<endl;
Recursive_Activity_Selector(s,f,0,length-1);
cout<<"Greedy_Activity_Selector:"<<endl;
Greedy_Activity_Selector(s,f,length-1);
cout<<"Dynamic_Activity_Selector:"<<endl;
Dynamic_Activity_Selector(s,f,length);
return 0;
}
原文地址:http://blog.csdn.net/luoshixian099/article/details/46559737