题目 会场安排问题
问题描述:假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场.设计一个有效的贪心算法进行安排.(这个问题实际上是著名的图着色问题.若将每一个活动作为图的一个顶点,不相容活动间用边相连.使相连顶点着不同颜色的最少着色数,相应于要找最少会场数.)
算法主要思想(贪心算法):按照活动开始时间排序,建立标志数组1为已安排,0为未安排。首先遍历数组寻找开始时间最早的且尚未被安排的活动,记下此活动。以此活动为基准在下一个循环中遍历开始时间大于此活动的结束时间的活动,然后记下此活动,继续寻找。如此循环上述步骤,直到所有活动都已被安排。
注意:输入时依次输入活动开始时间,结束时间,会议编号,会议是否被安排(用空格隔开,回车输入下一个活动的相关内容);且本程序非最优程序,还可优化。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
//最少会议室安排函数
void Welcome()//建立登陆首页面
{
printf("┍--------------------------------------------┑ \n");
printf("│ 欢迎使用本程序 │\n");
printf("│ 祝您使用愉快 │\n");
printf("┕--------------------------------------------┙\n");
system("pause");
}
int Quit()//退出程序
{
system("cls");
printf("┍--------------------------------------------┑ \n");
printf("│ 十分感谢您的使用 │\n");
printf("│ 希望下次继续为您服务 │\n");
printf("│ 稍后以任意键退出即可 │\n");
printf("┕------------------------------------------- ┙\n");
system("pause");
exit(0);
}
int greedySelector(int* a, int* f, int* arr, int* number, int n) {
int j = 0, k = 0, m = 0, count = 0;
while (count != n) { //已被安排的会议的数量,若会议已安排完则跳出循环
m++; //最少会议室数
for (j; j < n; j++) { //从未安排的会议中选择开始时间最早的
if (arr[j] == 0) { //0表示此会议未安排
arr[j] = 1; //1表示此会议已被安排
count++; //每安排一个会议count加1
k = j;
printf("%d会议已被安排在第%d会议室\n", number[j], m);
break; //选择到开始时间最早的会议后跳出循环,并将其记录
}
else
continue;
}
for (int i = 0; i < n; ++i) { //贪心算法,以选择的开始时间最早的且尚未被安排的
//会议为基准,继续安排时间上不冲突的会议
if (a[i] >= f[k] && arr[i] == 0) { //若开始时间大于或等于结束时间且未被安排,则可
//以安排在同一会议室
arr[i] = 1;
k = i; //更新被安排的会议的下标,用来记录该会议的结束时间
count++; //记录已安排的会议数量
printf("%d会议已被安排在第%d会议室\n", number[i], m);
}
else;
}
}
return m; //返回安排的最少会议室数量
}
//按开始时间排序函数
void sort(int a[], int f[], int number[], int n) {
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
if (a[i] > a[j]) {
int temp = a[i];
int temp1 = f[i];
int temp2 = number[i];
a[i] = a[j];
f[i] = f[j];
number[i] = number[j];
a[j] = temp;
f[j] = temp1;
number[j] = temp2;
}
}
}
}
//运行及输入活动函数
int RUN() {
int n;
printf("请输入事件个数(n):");
scanf("%d", &n);
int* a = (int*)malloc(sizeof(int) * n); //开始时间
int* f = (int*)malloc(sizeof(int) * n); //结束时间
int* number = (int*)malloc(sizeof(int) * n); //会议编号
int* arr = (int*)malloc(sizeof(int) * n);
printf("请依次输入各事件的开始时间,结束时间和会议编号:\n");
for (int i = 0; i < n; i++)
scanf("%d %d %d %d", &a[i], &f[i], &number[i],&arr[i]);
sort(a, f, number, n); //以会议开始时间从早到晚排序
//int arr[N] = { 0 }; //会议是否被安排的标志数组,1表示以安排,0未安排,初始化全为0未安排;
int num = greedySelector(a, f, arr, number, n);
printf("最少需要会议室%d个\n", num);
return 0;
}
int Menu()
{
Welcome();
system("cls");
int a;
printf("┍--------------------------------------------┑ \n");
printf("│ 功能目录 │\n");
printf("│ 1.运行程序 │\n");
printf("│ 2.退出程序 │\n");
printf("┕--------------------------------------------┙\n");
printf("请输入您需要的功能(编号):");
scanf("%d", &a);
while (a < 1 || a>2)
{
printf("抱歉,您的输入有问题,目前程序仅支持这些功能,请重新输入\n:");
scanf("%d", &a);
}
return a;
}
//主函数
int main()
{
for (;;)//无条件循环菜单栏达到每次完成功能后回到菜单栏继续工作的目的直到用户选择退出程序
switch (Menu())
{
case 1:RUN(); break; //运行
case 2:Quit(); break; //退出程序
}
return 0;
}