会场安排问题贪心算法

问题描述:

假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。设计一个有效的贪心算法进行安排(这个问题实际上是著名的图着色问题。若将每一个活动作为图的一个顶点,不相容活动间用边相连。使相邻顶点着有不同颜色的最小着色数,相应于要找的最小会场数)。

问题解答:

<1>、用贪心选择策略解会场安排问题。

贪心算法重要的两个性质:贪心选择性质和最优子结构性质。

1、 问题的贪心选择性质

证明:首先将会场安排问题数学化,设有n个活动的集合 e= { 1 ,2 ,…,n },每个活动 i 都有一个要求使用该会场的起始时问si 和一个结束时问fi 。即k是所需最少会场的个数。设活动已排序,( a1 , a2 , … ,ak )是所需要的k个已安排了活动的会场。①当k = 1时,也就是所有的活动在一个会场里相容,a1 是满足贪心选择性质的最优解;②当k>= 2时,取b1=a1,bk=ak (即bk是安排了m个活动的一个会场,(n-m)个活动都安排在b1 到bk-1个会场里)。就是(n-m)个活动安排需要(k -1)个会场。则(b1,b2 ,…,bk-1 )是(n - m)个活动可行解。另一方面,由{( a1 ,a2,…,ak)-ak}=(b1,b2,…,bk-1)知,(b1,b2,…,bk-1)也是满足贪心选择性质的最优解,所以,会场安排问题具有贪心选择性质。

2、 问题的最优子结构性质

证明:( a1,a2, …,ak )是n个活动的集合e= {1,2 ,…,n }所需会场的最优解。设a1中安排了m个相容的活动,那么也就是说(n-m)个活动完全安排需要k-1个会场。假设(n - m)个活动安排只需要k-2个会场或则更少的会场。也就是说n个活动安排只需要k-1个会场或者更少的会场就可以安排完,则前后出现矛盾。一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。

<2>、算法实现思路:

1)、首先定义一个时间类Node,有两个data,flag属性,其中data是时间值,flag是判断活动开始还是结束。

2)、对所有的时间对象按.data排序到一个数组中,其中选择归并排序方法进行排序。

3)、该算法的贪心选择的意义是使剩余的可安排时间段极大化,以便安排尽可能多的相容活动。依次取出该数组的数据,判断其属性flag,若是一个开始时间,则Count++,若是结束时间Count--,其中最大的Count值就是要求的最少的会场数。

<3>、算法程序:

#include
#include
using namespace std;

//活动的时间类
class Node
{
public:
    int data;//时间值
    bool flag;//判断是开始还是结束,0表示开始,1表示结束
    bool operator<(Node &secondRational);//按时间值比较两个对象的大小
};

//比较类中时间值的大小
bool Node::operator<(Node &secondRational)
{
    if((this->data-secondRational.data)<0)
        return true;
    else
        return false;
}

//复制数组函数
template
void arraycopy(T source[],int sourceStartIndex,T target[],int targetStartIndex,int length);
//合并数组函数
template
void merge(T list1[],int list1Size,T list2[],int list2Size,T temp[]);
//归并排序函数
template
void mergeSort(T list[],int arraySize)
{
    if(arraySize>1)
    {
        //复制排序前半部分数组
        T *firstHalf=new T[arraySize/2];
        arraycopy(list,0,firstHalf,0,arraySize/2);
        mergeSort(firstHalf,arraySize/2);

        //复制排序后半部分数组
        int secondHalfLength=arraySize-arraySize/2;
        T *secondHalf=new T[secondHalfLength];
        arraycopy(list,arraySize/2,secondHalf,0,secondHalfLength);
        mergeSort(secondHalf,secondHalfLength);

        //合并复制两部分数组
        T *temp=new T[arraySize];
        merge(firstHalf,arraySize/2,secondHalf,secondHalfLength,temp);
        arraycopy(temp,0,list,0,arraySize);

        delete []temp;
        delete []firstHalf;
        delete []secondHalf;
    }
}

//将两个数组按大小顺序合并入一个数组中
template
void merge(T list1[],int list1Size,T list2[],int list2Size,T temp[])
{
    int current1=0;
    int current2=0;
    int current3=0;

    while(current1
void arraycopy(T source[],int sourceStartIndex,T target[],int targetStartIndex,int length)
{
    for(int i=0;imaxCount)//记录次循环中最大的Count值
            {
                maxCount=Count;
            }
        }
        else//若为结束时间Count-1
        {
            Count--;
        }
    }
    return maxCount;
}

int main()
{
    //读出输入文件中的数据
    fstream fin;
    fin.open("input.txt",ios::in);
    if(fin.fail())
    {
        cout<<"File does not exist!"<>n;

    //建立两个Node类型的数组,用于存放开始时间和结束时间
    Node *a=new Node[n];
    Node *b=new Node[n];
    for(int i=0;i>a[i].data;
        fin>>b[i].data;
    }

    //将开始时间表示为0
    for(int j=0;j 
 

你可能感兴趣的:(贪心算法,算法,动态规划)