贪心法求解会场安排问题

实验内容:

        本实验要求基于算法设计与分析的一般过程(即待求解问题的描述、算法设计、算法描 述、算法正确性证明、算法分析、算法实现与测试),使用贪心法求解会场安排问题,以期 从实践中理解贪心法的思想、求解策略及步骤。有余力者,可以巩固单源最短路径、最小生 成树、哈夫曼编码等基于贪心策略的求解算法的练习。

实验目的:

◆ 理解贪心法的核心思想以及分治法求解过程。

实验步骤:

步骤 1:理解问题,给出问题的描述。

         设有 n 个会议的集合 C={1,2,…,n},其中每个会议都要求使用同一个资源(如会议 室),而在同一时间内只能有一个会议使用该资源。每个会议 i 都有要求使用该资源的起始时间 ai 和结束时间 bi,且 ai < bi 。如果选择了会议 i 使用会议室,则它在半开区间[ai, bi)内占用该资源。如果[ai, bi)与[aj , bj)不相交,则称会议 i 与会议 j 是相容的。会场安排问题要 求在所给的会议集合中选出最大的相容活动子集,也即尽可能地选择更多的会议来使用资源。

步骤 2:算法设计,包括算法策略与数据结构的选择;

        1.初始化。开始时间存入数组 A;结束时间存入数组 B 中且按照结束时间的非减序排 序,A 相应调整;集合 C 存储解,会议 i 如果在集合 C 中,当且仅当 C[i]=true;

        2.根据贪心策略,首令 C[1]=true;

        3.依次扫描每一个会议,如果会议 i 的开始时间不小于最后一个选入 C 中的会议的结束 时间,则将会议 i 加入 C 中;否则,放弃,继续检查下一个会议 C 中会议的相容性。

步骤 3:描述算法。希望采用源代码以外的形式,如伪代码、流程图等;

        要尽可能多的安排会议,显然采取贪最早结束时间的策略。

        设会议 i 的起始时间 ai 和结束时间 bi 的数据类型为整形(限制在整点);

        则 GreedySelector 算法描述如下:

        Void GreedySelector(int n,int b[ ],int e[ ],bool A[ ])

        { //b 中元素按非递减序排列,a 中对应元素做相应调整;

                int I,j;

                C[1]=true; //初始化选择会议的集合 C,只包含会议 1;

                j=1;i=2; //从第二(i)个会议开始寻找与会议 1(j)相容的会议;

               while(i<=n){

                        if(a[i]>=b[i])

                        {        

                                C[i]=true;j=I;

                        }

                        else

                                C[i]=false;

                }

        }

步骤 4:算法的正确性证明。这个环节,在理解的基础上对算法的正确性给予证明;

        设集合 D 为最优解集合,其中第一个集合为 k。如果 k=1,则说明该集合是贪心选择得 出的最优解。如果 k>1,令集合 E=(D-{k})U{1}。因为活动 1 的结束时间比活动 k 少,并且 集合 D 是相容的,所以集合 E 也是相容。两个集合的活动个数也是一样多的。因此集合 D 也 是该问题的最优解之一。

步骤 5:算法复杂性分析,包括时间复杂性和空间复杂性;

         该算法的时间复杂度为排序的复杂度:O(nlogn),空间复杂度为常数阶:O(1)。

步骤 6:算法实现与测试。附上代码;

        

#include <iostream>
#include <string>
using namespace std;

int greedySelector(int n,int s[],int f[],bool a[])
{
    a[1]=true;
    int j=1;
    int cot=1;
    int q=1;
    cout<<"安排后可以进行的会议:"<<endl;
    cout<<q<<" "<<s[j]<<" "<<f[j]<<endl;
    for(int i=2;i<=n;i++)
    {
        if(s[i]>=f[j])
        {
            q+=1;
            cout<<q<<" "<<s[i]<<" "<<f[i]<<endl;
            a[i]=true;
            j=i;
            cot++;
        }
        else
            a[i]=false;
    }
    return cot;
}
int main()
{
    int n;
    cout<<"会议总数:";
    cin>>n;
    int s[n],f[n];
    bool a[n];
    cout<<"输入会议开始和结束时间:"<<endl;
    for(int i=1;i<=n;i++)
    {
        cin>>s[i];
        cin>>f[i];
    }
    int cot;
    cot=greedySelector(n,s,f,a);
    cout<<"安排会议总数为:"<<cot<<endl;
    system("pause");
    return 0;
}

实验总结:

        贪心算法每个阶段的决策一旦做出就不可更改。不允许回溯。

        贪心算法和动态规划本质 上是对子问题树的一种修剪,两种算法要求问题都具有的一个性质就是子问题最优性。动态 规划方法代表了这一类问题的一般解法,我们自底向上构造子问题的解,对每一个子树的 根,求出下面每一个叶子的值,并且以其中的最优值作为自身的值,其它的值舍弃。而贪心 算法是动态规划方法的一个特例,可以证明每一个子树的根的值不取决于下面叶子的值,而 只取决于当前问题的状况。贪心算法的性质是所求问题的整体最优解可通过一系列局部最优 的选择获得。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值