算法导论第十六章——贪心算法.(C++版本)

本文介绍了一个基于C++实现的活动选择算法,通过递归贪心策略来找出一系列兼容活动的最大子集。该算法使用了动态内存分配,并实现了递归和贪心两种方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 #include <iostream>
#include <type_traits>
#include <initializer_list>
#include <memory>
template<typename T=int>
class ActivitySelector{
 private:
  T* StartTime;//开始时间集. 
  T* EndTime;//结束时间集. 
  
  int* BestSubset;//最大兼容活动兼容集.
  
  int scale;//问题规模.即数组中元素的数量. 
  public:
   template<typename U=typename std::enable_if< std::is_integral<T>::value, void>::type > 
   ActivitySelector(const std::initializer_list<U>& STime, const std::initializer_list<U>& ETime);
   
   ~ActivitySelector();
   
   void RecursiveActivity(const int& flag, const int& index=1);
   void print();
   void GreeyActivitySelector();
};
template<typename T>
template<typename U>//=typename std::enable_if< std::is_integral<T>::value, void>::type >//判断T和U的类型是否一致. 
ActivitySelector<T>::ActivitySelector(const std::initializer_list<U>& STime, const std::initializer_list<U>& ETime)
                    :StartTime(nullptr),
                     EndTime(nullptr),
                     BestSubset(nullptr),
                     scale(0)
{
 if(STime.size() != ETime.size()){
  throw std::bad_cast();
 }
 
 int temp=STime.size();
 scale=temp;
 this->StartTime=new U[temp];
 this->EndTime=new U[temp];
 this->BestSubset=new int[temp];
 std::uninitialized_copy_n(STime.begin(), STime.size(), StartTime);//由此可以看出动态分配内存返回的指针可以直接当首元素用. 
 std::uninitialized_copy_n(ETime.begin(), ETime.size(), EndTime);
 std::uninitialized_fill_n(BestSubset, temp, 0);
 
 std::cout<<"success"<<std::endl;
}
template<typename T>
ActivitySelector<T>::~ActivitySelector()
{
 if(StartTime != nullptr || EndTime != nullptr || BestSubset != nullptr){
  delete[] StartTime;
  delete[] EndTime;
  delete[] BestSubset;
 }
 
 std::cout<<"destroy it"<<std::endl;
}
template<typename T>
void ActivitySelector<T>::RecursiveActivity(const int& flag, const int& index)//递归贪心. 
{
 int m=flag+1;
 int n=index;
 
 while(m < scale && StartTime[m] < EndTime[flag]){
  ++m;
 }
 //std::cout<<m<<"  ";
 if(m < scale){
  this->BestSubset[n]=m;
  ++n;
  this->RecursiveActivity(m, n);
 }
 
}
template<typename T>
void ActivitySelector<T>::print()
{
 if(BestSubset != nullptr){
  for(int i=0; i<scale; ++i){
   std::cout<<this->BestSubset[i]<<"  ";
  }
  std::cout<<std::endl;
 }
}
template<typename T>
void ActivitySelector<T>::GreedyActivitySelector()
{
 int i;
 int m;
 *(BestSubset)=1;//假设StartTime和EndTime中的第一个总是位于最优解中. 
 i=1;
 
 int index=1;
 for(m=2; n<scale; ++m){
  if(this->StartTime[m] >= this->EndTime[1]){
   this->BestSubset[index]=m;
   ++index;
   i=m;
  }
 }
 
}
int main()
{
 ActivitySelector<> myParty({-1, 1, 3, 0, 5, 3, 5, 6, 8, 8, 2, 12}, {-1, 4, 5, 6, 7, 9, 9, 10, 11, 12, 14, 16});
 //注意这里的 StartTime[0]和EndTime[0]都是小于0的,再来看EndTime是一个排序过的数组因此最先开始和结束的结局一般基本上来说都会是第一个.
  
 myParty.RecursiveActivity(0, 0);
 myParty.print();
 return 0;
}

转载于:https://my.oschina.net/SHIHUAMarryMe/blog/546785

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值