算法设计:实验二贪心算法

【实验目的】

应用贪心算法求解活动安排问题。

【实验要求】

活动安排问题是可以用贪心算法有效求解的很好的例子。

问题:有n个活动的集合A={1,2,...,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。

求解:安排尽量多项活动在该场地进行,即求A的最大相容子集。

设待安排的11个活动的开始时间和结束时间按结束时间的升序排列如下:

|--------|---|---|---|---|---|---|----|----|----|----|----|
| i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| s[i] | 1 | 3 | 0 | 5 | 3 | 5 | 6 | 8 | 8 | 2 | 12 |
| f[i] | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |

将此表数据作为实现该算法的测试数据。

【算法思想及处理过程】

贪心算法是一种基于贪心策略的算法,它在每一步选择中都采取当前状态下最优的选择,以期望能够获得全局最优解。它通常适用于满足以下两个条件的问题:

最优子结构性质:问题的最优解包含了其子问题的最优解。

贪心选择性质:通过局部最优选择,能够导出全局最优解。

贪心算法的基本思想是通过每一步的局部最优选择来构建问题的解决方案,从而实现对问题的全局最优解。它不像动态规划算法那样考虑所有可能的选择并进行比较,而是在每一步选择中只考虑局部最优解,然后逐步构建出全局最优解。

对于活动安排问题,贪心算法的思想是:

1.首先,按照活动的结束时间对活动进行升序排序。

2.选择第一个活动,并将其加入到最大相容子集中。

3.对于剩余的活动,依次检查每个活动的开始时间是否晚于等于前一个选中活动的结束时间,如果是,则将该活动加入到最大相容子集中。

4.重复步骤 3,直到所有活动都被检查完毕。

对于我的思路为:

  1. 对活动按照结束时间进行升序排序。

  2. 初始化一个结果列表,将第一个活动加入结果中。

  3. 遍历剩余的活动,依次检查每个活动的开始时间是否晚于等于前一个选中活动的结束时间。

  4. 如果是,则将该活动加入结果中,并更新最后选中活动的索引。

  5. 重复步骤 3 和步骤 4,直到所有活动都被检查完毕。

  6. 返回结果列表,即为最大相容子集。

流程图为:

同时为了跟好的记录数据,我创建了一个结构体Activity来记录活动的开始时间与结束时间

同时为了保证程序的正确性加入了check函数来保证不会出现相同的活动名,与此同时还会判断活动时间的正确性。

【程序代码】

#include <stdio.h>
#define MaxSize 9999

struct Activity {
	char name[MaxSize];
    int start;
    int finish;
};

int check(struct Activity activities[], int current, char name[]) {
	int i;
    for (i = 0; i < current; i++) {
        if (strcmp(activities[i].name, name) == 0) {
            return 0; // 发现重复的活动名
        }
    }
    return 1; // 没有发现重复的活动名
}

void activitySelection(struct Activity activities[], int n) {
    int i, j;

    // 按结束时间升序排序活动 
    for (i = 0; i < n-1; i++) {
        for (j = 0; j < n-i-1; j++) {
            if (activities[j].finish > activities[j+1].finish) {
                struct Activity temp = activities[j];
                activities[j] = activities[j+1];
                activities[j+1] = temp;
            }
        }
    }

    // 初始化结果列表,将第一个活动加入结果中
    printf("选中的活动:\n");
    printf("%s:(%d, %d)\n",activities[0].name, activities[0].start, activities[0].finish);
    // 从第二个活动开始遍历
    int next = 0;
    for (i = 1; i < n; i++) {
        // 如果当前活动的开始时间晚于等于前一个选中活动的结束时间,则将该活动加入结果中
        if (activities[i].start >= activities[next].finish) {
            printf("%s:(%d, %d)\n",activities[i].name, activities[i].start, activities[i].finish);
            next = i;
        }
    }
}

int main() {
    int n,i;
    printf("请输入活动个数:");
    scanf("%d", &n);

    struct Activity activities[n];
    printf("请输入每个活动的开始时间和结束时间(中间用空格隔开):\n");
    for (i = 0; i < n; i++) {
    	fflush(stdin);
        printf("活动名:");
        gets(activities[i].name);
        while(check(activities,i,activities[i].name) == 0){
        	printf("活动名重复,请重新输入:");
        	gets(activities[i].name);
        }
        printf("活动时间:");
        scanf("%d %d", &activities[i].start, &activities[i].finish);
        while((activities[i].start > activities[i].finish) || (activities[i].start == activities[i].finish)){
        	printf("活动时间输入违反规则,请重新输入:");
        	scanf("%d %d", &activities[i].start, &activities[i].finish);
        }
    }

    activitySelection(activities, n);

    return 0;
}

【运行结果】

【算法分析】

  1. 读取输入数据:这一步的时间复杂度为 O(n),其中 n 是活动的数量,因为需要对每个活动读取其开始时间和结束时间。

  2. 对活动按结束时间升序排序:排序的时间复杂度取决于排序算法。在你的程序中,使用的是冒泡排序算法,其平均时间复杂度为 O(n^2)。虽然这不是最优的排序算法,但由于活动数量通常不会太大,因此对时间复杂度的影响并不太大。

  3. 选择最大相容子集:在排序完成后,遍历一次活动数组并检查每个活动的开始时间是否晚于等于前一个选中活动的结束时间。由于只需要一次遍历,因此时间复杂度为 O(n)。

因此,总体时间复杂度为 O(n^2),其中 n 是活动的数量。

相关推荐
钢板兽14 分钟前
力扣hot100——子串、普通数组、矩阵
java·后端·算法·leetcode·面试·矩阵
丶重明16 分钟前
【Go每日一练】实现简单的控制台计算器
服务器·算法·golang
小竹子1430 分钟前
L3-1 夺宝大赛
数据结构·算法·图论
LDG_AGI38 分钟前
【深度学习】多元物料融合算法(一):量纲对齐常见方法
人工智能·深度学习·算法·机器学习·均值算法·哈希算法·启发式算法
EDPJ41 分钟前
(2025|ICLR|厦大&华为,LoSA,基于表示互信息的动态层级稀疏率,基于重构误差的秩分配)LLM 的动态低秩稀疏自适应
深度学习·算法·语言模型
KangkangLoveNLP44 分钟前
从Swish到SwiGLU:激活函数的进化与革命,qwen2.5应用的激活函数
人工智能·深度学习·神经网络·算法·机器学习·自然语言处理·cnn
奔跑的废柴1 小时前
LeetCode 513. 找树左下角的值 java题解
java·算法·leetcode
Awesome Baron1 小时前
LeetCode hot 100 每日一题(7)--3. 无重复字符的最长子串
算法·leetcode·职场和发展
SsummerC1 小时前
【leetcode100】组合总和
数据结构·python·算法·leetcode
反方向的钟儿2 小时前
【数学建模】001
笔记·算法·数学建模