貪心算法-會場安排問題


問題描述:假設要在足夠多的會場里安排一批活動,並希望使用盡可能少的會場。設計一個有效的貪心算法進行安排。(這個問題實際上是著名的圖着色問題。若將每個活動作為圖的一個頂點,不相容活動間用邊相連。使用相鄰頂點着有不同顏色的最小着色數,相應於要找的最小會場數)。

[之所以想記錄這個問題,就在於括號內的描述。看完題目的描述,我心想:圖着色問題不是有一個四色定理。換而言之,即任何活動,只要四個會場就夠了。而這顯然不符合常理。后來發現,問題在於四色定理只適用於地圖,在地圖上最多四個國家相互接壤。而活動顯然不滿足這個條件]

算法描述:

算法實現:

#include<stdio.h>
#include<stdlib.h>
void makemap(int **map,int *early,int *late,int n)
{
    for(int i=0;i<n;i++)//當前被判斷活動
        for(int j=i+1;j<n;j++)//其余活動
        {
            if((early[i]>=early[j]&&early[i]<=late[j])||
(late[i]>=early[j]&&late[i]<=late[j]))
            {//判斷當前活動與其余活動是否交叉  
                map[i][j]=map[j][i]=1;//交叉的話在圖上做標記
                map[i][i]++;//記錄與當前活動交叉活動的數目
                map[j][j]++;
            }
        }
}//標記交叉活動
void sortpoint(int **map,int *node,int low,int high)
{
 int i,j,temp,t,x;
 if(low<high)
 {
  t=rand()%(high-low+1)+low;
  temp=node[t];
  node[t]=node[low];
  node[low]=temp;

  i=low;
  j=high;
  x=node[i];
  do
  {
   while(i<j && map[node[j]][node[j]]>=map[x][x]) j--;
   if(i<j) {node[i]=node[j];i++;}
   while(i<j && map[node[i]][node[i]]<map[x][x]) i++;
   if(i<j) {node[j]=node[i];j--;} 
  }while(i!=j);
  node[i]=x;
  sortpoint(map,node,low,i-1);
  sortpoint(map,node,i+1,high);
 }
}//依照活動與其他活動交叉的數目對活動進行隨機快速排序
 //形成遞增序列
void colorit(int **map,int *node,int n)
{
    int *color;
    color=(int *)malloc((sizeof(int))*n);
    for(int i=0;i<n;i++)color[i]=0;
    color[node[n-1]]=0;    
    for(int i=n-2;i>=0;i--)
    {
        int elem[5]={0,0,0,0,0};
        for(int j=i+1;j<n;j++)
          if(map[i][j])elem[color[j]]=1;
       //根據圖五色原理
       //設置數組標記與當前活動交叉且已分配會場的活動的舉辦會場
        for(int j=0;j<5;j++)
          if(elem[j]==0)
          {
              color[i]=j;
              break;
          }
       //根據標記會場數組分配當前活動舉辦會場
    }
    int count=0;
    for(int i=0;i<n;i++)
        if(color[i]>count)count=color[i]; 
    count++;
    printf("%d",count);
    //統計開設會場的數目(結果) 
}//為每個活動分配會場
int main()
{
    int n;
    scanf("%d",&n);
   //活動數目n
    int **map;
    map=(int **)malloc((sizeof(int *))*n);
    for(int i=0;i<n;i++)
    map[i]=(int *)malloc((sizeof(int))*n);
    //用於記錄活動間的交叉情況
    int *early;
    int *late;
    early=(int *)malloc((sizeof(int))*n);
    late=(int *)malloc((sizeof(int))*n);
    //用於記錄活動的開始時間和結束時間
    for(int i=0;i<n;i++)
    {
        scanf("%d %d",&early[i],&late[i]);
        for(int j=0;j<n;j++)map[i][j]=0;
    }
    makemap(map,early,late,n);
    int *node;
    node=(int *)malloc((sizeof(int))*n);
    for(int i=0;i<n;i++)node[i]=i;
    sortpoint(map,node,0,n-1);
    colorit(map,node,n);    
    return 0;
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM