C语言-实现数学排列组合里的排列算法

本文将编写一个函数实现数学排列的功能,采用的办法是递归。具体功能如图所示:

在这里插入图片描述

一、函数的讲解

1.1 函数的原型
函数的原型:int** Permutation(int* iarr,int size);
将数组的首地址和数组的大小传递进去,函数将返回一个二维数组的地址,这个二维数组包含n!个一维数组(n即是size),而每一个一维数组又包含size个元素,二维数组的大小为n! * n

1.2 递归的大概思路(如图所示)
假设要数组的大小(size)为4,则要返回一个4!* 4大小的二维指针。
在这里插入图片描述

二-0 伪代码

伪代码#01:全排列,递归法。

输入:A[1...n
  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
下面是贪心算法活动安排问题的C语言实现: ```c #include <stdio.h> #include <stdlib.h> // 活动结构体 typedef struct Activity { int start; // 开始时间 int end; // 结束时间 } Activity; // 比较函数,按结束时间升序排列 int cmp(const void *a, const void *b) { return ((Activity*)a)->end - ((Activity*)b)->end; } // 贪心算法 int activitySelection(Activity *activities, int n) { int count = 1; // 计数器,记录已安排的活动数 int end = activities[0].end; // 记录上一个已安排活动的结束时间 for (int i = 1; i < n; i++) { if (activities[i].start >= end) { count++; end = activities[i].end; } } return count; } int main() { int n; printf("请输入活动数:"); scanf("%d", &n); Activity *activities = (Activity*)malloc(n * sizeof(Activity)); printf("请按开始时间和结束时间的顺序依次输入每个活动的时间:\n"); for (int i = 0; i < n; i++) { scanf("%d %d", &activities[i].start, &activities[i].end); } qsort(activities, n, sizeof(Activity), cmp); // 按结束时间升序排列 printf("最多可以安排%d个活动\n", activitySelection(activities, n)); free(activities); return 0; } ``` 该实现中,我们使用了结构体来存储活动的开始时间和结束时间,使用了qsort函数来按结束时间升序排列,使用了activitySelection函数来实现贪心算法的核心逻辑。 对于数学模型的建立,我们可以将活动安排问题看作是一个集合覆盖问题,其中每个活动代表一个集合,集合中包含的元素是活动的时间段,我们需要选择尽可能少的集合,使得它们的并集覆盖了所有的元素。因此,我们可以使用一个数组来存储活动的开始时间和结束时间,使用一个二维数组来表示集合与元素之间的关系,例如: ```c int sets[MAX_SETS][MAX_ELEMENTS]; // 集合与元素之间的关系 ``` 其中,MAX_SETS表示最大集合数,MAX_ELEMENTS表示每个集合中最多包含的元素数。对于每个活动i,我们可以将其时间段表示为一个集合Si,其中元素j表示时间段中的第j个时间点,例如: ```c for (int i = 0; i < n; i++) { for (int j = activities[i].start; j <= activities[i].end; j++) { sets[i][j] = 1; // 时间点j属于集合Si } } ``` 然后,我们可以使用贪心算法来选择最少的集合,使得它们的并集覆盖了所有的元素,例如: ```c int selected[MAX_SETS] = {0}; // 记录已经选择的集合 int count = 0; // 记录已经选择的集合数 for (int j = 0; j < MAX_ELEMENTS; j++) { int max_cover = 0; // 记录当前元素被最多集合覆盖的次数 int max_set = -1; // 记录覆盖当前元素最多的集合 for (int i = 0; i < MAX_SETS; i++) { if (!selected[i] && sets[i][j] && cover[i] > max_cover) { max_cover = cover[i]; max_set = i; } } if (max_set != -1) { selected[max_set] = 1; count++; for (int k = 0; k < MAX_ELEMENTS; k++) { if (sets[max_set][k]) { cover[k]++; } } } } ``` 其中,selected数组记录已经选择的集合,cover数组记录每个元素被覆盖的次数。该算法的时间复杂度为O(MAX_SETS * MAX_ELEMENTS ^ 2),其中MAX_SETS表示集合数,MAX_ELEMENTS表示每个集合中最多包含的元素数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值