假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场.设计一个有效的贪心算法进行安排。
这个问题先要使用贪心算法,那么将所有活动用贪心算法排一遍,然后将剩下活动里剩下的活动继续用贪心算法解决,一直到把所有的活动都安排完。每用一次贪心算法,会场数+1.直到吧活动安排结束。
使用贪心算法的前提是:将活动按照活动结束时间非减序排列。
这样就把整个问题解决了。
下面看看具体实现:
#include<stdio.h>
#include<Windows.h>
#pragma warning(disable:4996)
#define NUM 100
void resort(int *f,int *s,int n){
int i = 0;
int j = 0,k=0;
for (; j < n; j++){
for (k=j+1; k < n ; k++){
if (*(f + j)>*(f + k)){
int temp = *(f + j);
*(f + j) = *(f + k);
*(f + k) = temp;
int temp1 = *(s + j);
*(s + j) = *(s + k);
*(s + k) = temp1;
}
}
}
while (i < n){
printf("第%d个s:%d ", i + 1, *s++);
printf("第%d个f:%d ", i+1,*f++);
i++;
printf("\n");
}
}
void greedy(int *f,int *s,int *c,int n1){
int i = 0,n=i,j=0;
for (i = 0; i < n1; i++){
if (*(c + i) == 0){
if (j == 0){//数组c里面第一个为0的元素,对应下标的活动被标记。
*(c + i) = 1;
}
j++;
}
if (*(f + n) <= *(s + i + 1)){
*(c + i + 1) = 1;
n = i + 1;
}
else{
continue;
}
}
i = 0;
while (i<n1){
printf("%d ", c[i]);
i++;
}printf("\n");
}
int Getnumber(int *f,int *s,int *c,int n2){
int i = 0,flag=n2+1;
int sum=0;
while (flag){
int jud = 0;
for (i = 0; i < n2; i++){
jud = jud + *(c + i);
}
if (jud == n2){
return sum;
break;
}
else{
//c[i]的值为1表示,该值下标的f,s数组元素已经被排好。反之还未被排序
greedy(f,s,c,n2);
sum++;
}flag--;
}
}
int main(){
int f[NUM] = { 0 };
int s[NUM] = {0};
int ci[NUM] = {0};
int num = 1;
printf("请输入活动数目:" );
scanf("%d", &num);
for (int i = 0; i < num; i++){
printf("第%d个活动的开始时间:", i + 1);
scanf("%d", &s[i]);
printf("第%d个活动的结束时间:", i + 1);
scanf("%d", &f[i]);
printf("\n");
}
resort(f, s,num);
printf("需要%d个场地!\n",Getnumber(f,s,ci,num));
system("pause");
return 0;
}
大概讲一下,这里的f数组表示,将活动结束时间存入。s数组里面存的是活动开始时间。
resort函数是对活动结束时间进行非减序排列。即f数组按照增序排列,对应的也将s数组改变顺序。这样就将活动排好序了。
ci数组是用来表示对应下标的活动是否被安排,如果被安排,则将该下标ci元素置1,否则为0,。
这里我使用了getnumber函数调用greedy函数。调用条件是:如果有n个活动,那么ci数组的前n项的和为n的话就会循环结束,得到会场数,否则就一直调用greedy函数。
这样就写完了这个题目。