贪心算法解决会场安排问题

文章介绍了如何使用贪心策略解决最大相容会议安排问题,通过数组数据结构对会议按结束时间排序,然后依次选择开始时间不晚于上一个选中的会议结束时间的会议,最后证明了算法的正确性和复杂性分析。
摘要由CSDN通过智能技术生成

问题的描述

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

算法设计

算法策略:贪心策略

数据结构:数组

  1. 初始化,并按会议结束时间非减序排序:开始时间存入数组B中,结束时间存入数组E中;按照结束时间的非减序排序E,B需做相应的调整;集合A存储解,如果会议i再集合A中,当且仅当其被选中。
  2. 根据贪心策略,做第一次贪心选择:令A[1]=1。
  3. 依次扫描每一个会议,直至所有会议检查完毕:如果会议i的开始时间不小于最后一个选入A中的会议的结束时间,则将会议i加入A中;否则,放弃并继续检查下一个会议与A中会议的相容性。

 描述算法(伪代码)

GREEDY-ACTIVITY-SELECTOR (B , E)

       SORT-ASC-BY-F(B,E)   //对E按非减序排序并同调整E

       N=B.length

       A={1}      //首先选择会议1

       K=1        //已被选择会议集合中最晚结束的会议(k)

       for m=2 to n

              if B[m]>=E[k]        //会议m的开始时间不小于会议k的结束时间

                     then A=A∪{m}     //将会议m加入到集合A中

                     k=m       //此时集合A中最晚结束的会议为m

       return A

算法的正确性证明

假设最优解不含贪心选择,即最优解A的某个活动a所选择的会场r‘不是结束时间最早的会场r,由于r的结束时间小于r’,a能在r中进行,说明a必定能在r中进行,因此用r代替r‘的结果(A-{r’})∪{r}仍是一个最优解,即最优解包含贪心选择,与假设矛盾。

算法复杂性分析

时间复杂性:O(nlogn)+O(n)->O(nlogn)

空间复杂性:O(logn)+O(1)->O(logn)

算法实现与测试

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int N;
int b[30];
int e[30];
bool a[30];

void GreedSelector();
void swap();
void timesort();


int main()
{
	cout<<"输入会议个数:";
	cin>>N;	//会议个数
	cout<<"分别输入每个会议的开始时间和结束时间:"<<endl;
	for(int i=1;i<=N;i++){
		cin>>b[i]>>e[i];		
	} 
	fill(a,a+N,0);
	timesort();
	GreedSelector();
	return 0;
	
}

void GreedSelector()
{
	int i,j;
	a[1]=true;
	j=1;
	i=2;
	for(i=2;i<=N;i++){
		if(b[i]>=e[j]){
			a[i]=true;
			j=i;
		}else{
			a[i]=false;
		}
	}
	cout<<"会议集合为{"; 
	for(int i=1;i<=N;i++){
		if(a[i]){
			cout<<i<<" ";
		}
	}
	cout<<"}"<<endl;
}

void swap(int a,int b){
	int t;
	t=a;
	a=b;
	b=t;
}

void timesort(){
	int i,j;
	for(j=1;j<N+1;j++){
		for(i=1;i<N+1-j;i++){
			if(e[i]>e[i+1]){
				swap(e[i],e[i+1]);
				swap(b[i],b[i+1]);
			}
		}
	}
	
	cout<<"按结束时间排序后的会议排列表:"<<endl;
    for(i=1;i<=N;i++){
        cout<<i<<"  ";
    }
    cout<<endl;
    for(i=1;i<=N;i++){
        cout<<b[i]<<"  ";
    }
    cout<<endl;
    for(i=1;i<=N;i++){
        cout<<e[i]<<"  ";
    }
    cout<<endl;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值