活动安排问题#c语言#含解释

本文介绍了一个活动安排问题的解决方案,通过输入n个活动的起始和结束时间,使用qsort对活动进行排序,找到最大的相容活动子集,即在同一时间段内不冲突的活动数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【活动安排问题】设有n个活动的集合E={1,2,...n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和fi,且si<fi。如果选择了活动i,则它在半开时间区间[si,fi)内占用资源。若区间[si,fi)和[sj,fj)不相交,则称活动i和活动j是相容的。活动安排问题就是要在所给的活动集合中选出最大的相容活动子集和。

#include <stdio.h>  // 引入标准输入输出头文件
#include <stdlib.h> // 引入标准库头文件,用于调用qsort等函数

// 定义一个比较函数,用于qsort排序
int compare(const void *a, const void *b) {
    const int *x = (const int *)a; // 将void指针转换为int指针
    const int *y = (const int *)b; // 同上
    if (x[1] < y[1]) { // 如果第一个活动的结束时间小于第二个活动的结束时间
        return -1; // 返回-1,表示第一个活动排在前面
    } else {
        return 1; // 否则返回1,表示第二个活动排在前面
    }
}

// 主函数
int main() {
    int n; // 定义一个整数n,用于存储活动的数量
    scanf("%d", &n); // 使用scanf从标准输入读取一个整数,存储到n中
    
    int sf[n][2]; // 定义一个二维数组sf,用于存储活动的时间信息
    for (int i = 0; i < n; i++) { // 循环n次,读取每个活动的时间信息
        scanf("%d %d", &sf[i][0], &sf[i][1]); // 使用scanf读取活动的起始时间和结束时间
    }
    
    qsort(sf, n, sizeof(int) * 2, compare); // 使用qsort对数组sf进行排序,每次排序两个整数
    
    // 打印排序后的数组,供参考
    for (int i = 0; i < n; i++) {
        printf("%d %d\n", sf[i][0], sf[i][1]); // 打印每个活动的起始时间和结束时间
    }
    
    int f = 0, cont = 0; // 定义两个整数f和cont,分别用于存储当前活动的结束时间和活动计数
    for (int i = 0; i < n; i++) { // 循环n次,处理每个活动
        if (sf[i][0] >= f) { // 如果当前活动的起始时间大于或等于f
            f = sf[i][1]; // 更新f为当前活动的结束时间
            cont++; // 活动计数加1
        }
    }
    
    printf("%d\n", cont); // 打印活动计数
    
    return 0; // 程序结束
}

运行结果:

在C语言中,我们可以使用动态规划来解决活动安排问题。这里以0-1背包问题为例,因为它的本质类似,都是寻找最大收益。假设我们有一个包n项任务的列表,每项任务都有开始时间和结束时间,以及对应的收益值。我们的目标是在有限的时间内选择能够获取最高收益的任务。 以下是简单的C语言代码示例: ```c #include <stdio.h> #include <stdlib.h> // 定义结构体表示任务 typedef struct { int start; // 开始时间 int end; // 结束时间 int reward; // 收益值 } Task; // 动态规划函数 int maxProfit(int tasks[], int n, int time) { int dp[time + 1]; // 状态数组,dp[i]表示在t时间内能获得的最大收益 for (int i = 0; i <= time; i++) { dp[i] = 0; // 初始化所有时间下的收益为0 } for (int i = 0; i < n; i++) { // 遍历所有任务 for (int j = tasks[i].start; j <= time; j++) { // 只考虑在活动开始到当前时间点之间 if (j >= tasks[i].end) { // 如果该任务在当前时间点之前结束 dp[j] = max(dp[j], dp[j - tasks[i].start] + tasks[i].reward); // 更新状态,取最优策略 } } } return dp[time]; // 返回在指定时间内能获得的最大收益 } int main() { Task tasks[] = { {1, 3, 1}, {2, 4, 5}, {3, 6, 8} }; // 三个任务示例 int n = sizeof(tasks) / sizeof(Task); int total_time = 6; // 总时间 printf("Max profit in %d time units is: %d\n", total_time, maxProfit(tasks, n, total_time)); return 0; } ``` 这段代码首先创建了一个状态数组`dp`,然后遍历所有任务,对于每一个任务,都在其可能的开始时间范围内更新dp数组。最后返回`dp[total_time]`即为最大收益。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值