C语言实现:贪心算法

算法基础原理

 贪心算法是一种在求解问题时,总是做出在当前看来是最好的选择的算法。它不从整体最优上进行考虑,而是通过每一步的局部最优选择,希望达到全局的最优解.

贪心算法的特点:贪心算法在每一步都选择当前状态下的最优解,即局部最优解,同时贪心算法采用自顶向下的方式,以迭代的方法做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为一个规模更小的子问题。虽然每一步都保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪心算法不要回溯。

贪心算法包含以下几种分支:

  1. 标准贪心算法
    • 活动选择问题:选择最大数量的不重叠活动。
    • 埃及分数问题:将真分数表示为一系列不重复的倒数之和。
    • 霍夫曼编码:用于数据压缩,构建最优前缀码。
    • 水连接问题:用最少的管子连接所有的房子。
  2. 图中的贪心算法
    • Kruskal的最小生成树算法:通过不断加入最小的边来构建最小生成树。
    • Prim的最小生成树算法:从一个顶点开始,每次加入连接已选顶点和未选顶点之间的最小边。
    • Dijkstra的最短路径算法:用于找到图中单源最短路径。
  3. 数组中的贪心算法
    • 数组的最小乘积子集问题:选择数组中某些数,使得它们的乘积最小。
    • 最大化数组总和问题:在限定操作次数下最大化数组的总和。
    • 其他与数组相关的最大化或最小化问题,如最大化连续差异的总和等。

贪心算法的基础流程如下: 

代码实现 

金钱找零 

先定义一个包含四种面值纸币的数组coins和一个记录每种硬币数量的数组coin_countgreedyChange函数接收一个整数money作为输入,表示需要找零的金额。函数通过遍历coins数组,从最大面值的纸币开始,尽可能多地使用每种面值的纸币,直到找零完成或无法找零。如果找零成功,它会打印出总共需要的纸币数量和每种面值纸币的数量;如果无法找零,它会打印出“无法找零”。最后main函数从用户那里获取要找零的金额,并调用greedyChange函数进行处理。

#include <stdio.h>  
  
// 定义可用纸币面值  
int coins[] = {20, 10, 5, 1};  
#define NUM_COINS 4 // 定义需要纸币的数量  
int coin_count[NUM_COINS] = {0}; // 设置一个全局变量用于记录每种硬币的数量  
  
void greedyChange(int money) {  
    int i, count = 0;  
    for (i = 0; i < NUM_COINS; i++) { // 使用NUM_COINS宏   
        while (money >= coins[i]) {  
            money -= coins[i];  
            coin_count[i]++; // 修改全局变量,不需要前缀global_  
            count++;  
        }  
    }  
    if (money != 0) {  
        printf("无法找零\n");  
        return;  
    }  
    printf("总共需要 %d 张money\n", count);  
    for (i = 0; i < NUM_COINS; i++) { 
        if (coin_count[i] != 0) {  
            printf("面值 %d 的纸币需要 %d 张\n", coins[i], coin_count[i]);  
        }  
    }  
    // 清零全局的coin_count数组以供下次使用  
    for (i = 0; i < NUM_COINS; i++) { 
        coin_count[i] = 0;  
    }  
}  
  
int main() {  
    int money;  
    printf("请输入要找零的金额: ");  
    scanf("%d", &money);  
    greedyChange(money);  
    return 0;  
}

计算连续插值的最大和

先提示用户输入数组元素的数量,并动态分配相应大小的内存来存储这些元素。接着要求用户输入指定数量的整数,并将这些整数存储在之前分配的数组中。然后调用maxDifferenceSum函数来计算数组中任意两个连续元素之间差值的绝对值之和的最大值。这个函数通过两层循环遍历数组,外层循环确定起始位置,内层循环计算从当前起始位置到数组末尾的所有连续差值的绝对值之和,并在过程中更新最大和。最后打印出连续差值的最大和,并释放之前动态分配的内存。 

#include <stdio.h>  
#include <stdlib.h>  
#include <math.h>  
  
int maxDifferenceSum(int arr[], int n) {  
    int maxSum = 0;  
    for (int i = 0; i < n; i++) {  
        int currentSum = 0;  
        for (int j = i; j < n - 1; j++) {  
            currentSum += abs(arr[j] - arr[j + 1]);  
            if (currentSum > maxSum) {  
                maxSum = currentSum;  
            }  
        }  
    }  
    return maxSum;  
}  
  
int main() {    
    int n;  
    printf("请输入数组元素的数量: ");  
    scanf("%d", &n);  
  
    // 动态分配数组内存  
    int *arr = (int *)malloc(n * sizeof(int));  
    if (arr == NULL) {  
        printf("内存分配失败!\n");  
        return 1;  
    }  
  
    printf("请输入 %d 个整数:\n", n);  
    for (int i = 0; i < n; i++) {  
        scanf("%d", &arr[i]);  
    }  
  
    int result = maxDifferenceSum(arr, n);    
    printf("连续差值的最大和为: %d\n", result);    
    // 释放动态分配的内存  
    free(arr);  
  
    return 0;    
}

流程图的Markdown mermaid代码

基础流程: 

graph TB  
    A[开始]  
    B[初始化候选集合]  
    C[选择当前最优解]  
    D[更新候选集合]  
    E[判断候选集合是否为空]  
    F[是,算法结束]  
    G[否,继续选择]  
    H[将当前最优解加入结果集]  
  
    A --> B  
    B --> C  
    C --> H  
    H --> D  
    D --> E  
    E --> F  
    E --> G  
    G --> C

 C语言实现找零钱流程:

graph TB  
    A["开始"]  
    B["输入要找零的金额"]  
    C["调用greedyChange函数"]  
    D["初始化count为0"]  
    E["遍历每种纸币面值"]  
    F["当前纸币面值能否找零"]  
    G["减去当前纸币面值,增加纸币计数,增加count"]  
    H["判断是否仍有余额需要找零"]  
    I["输出无法找零"]  
    J["输出总纸币张数"]  
    K["输出每种纸币的面值和数量"]  
    L["清零全局coin_count数组"]  
    M["结束"]  
  
    A --> B  
    B --> C  
    C --> D  
    D --> E  
    E --> F  
    F -->|是| G  
    G --> H  
    F -->|否| H  
    H -->|仍有余额| I  
    H -->|无余额| J  
    J --> K  
    K --> L  
    L --> M  
    I --> M

C语言计算连续插值的最大和

graph TB  
    A[开始]  
    B[提示用户输入数组元素数量]  
    C[读取用户输入的数组元素数量]  
    D[动态分配数组内存]  
    E[检查内存分配是否成功]  
    F[内存分配失败]  
    G[提示用户输入指定数量的整数]  
    H[读取用户输入的整数并存入数组]  
    I[调用maxDifferenceSum函数计算连续差值的最大和]  
    J[打印连续差值的最大和]  
    K[释放动态分配的内存]  
    L[结束]  
  
    A --> B  
    B --> C  
    C --> D  
    D --> E  
    E --> |成功| G  
    E --> |失败| F  
    F --> L  
    G --> H  
    H --> I  
    I --> J  
    J --> K  
    K --> L
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C语言实现贪心算法的背包问题,可以按照以下步骤进行: 1. 首先,定义一个结构体来表示物品,包括物品的价值和重量。例如: ```c struct Item { int value; int weight; }; ``` 2. 接下来,定义一个函数来比较两个物品的价值密度(价值与重量的比值),并按照价值密度从大到小排序物品数组。例如: ```c int compare(const void* a, const void* b) { struct Item* item1 = (struct Item*)a; struct Item* item2 = (struct Item*)b; double ratio1 = (double)item1->value / item1->weight; double ratio2 = (double)item2->value / item2->weight; if (ratio1 < ratio2) { return 1; } else if (ratio1 > ratio2) { return -1; } else { return 0; } } void sortItems(struct Item items[], int n) { qsort(items, n, sizeof(struct Item), compare); } ``` 3. 然后,实现贪心算法的背包问题解决函数。该函数接受背包容量和物品数组作为参数,并返回背包中物品的总价值。例如: ```c int knapsackGreedy(struct Item items[], int n, int capacity) { sortItems(items, n); int totalValue = 0; int currentWeight = 0; for (int i = 0; i < n; i++) { if (currentWeight + items[i].weight <= capacity) { totalValue += items[i].value; currentWeight += items[i].weight; } else { int remainingCapacity = capacity - currentWeight; totalValue += items[i].value * ((double)remainingCapacity / items[i].weight); break; } } return totalValue; } ``` 这样,你就可以调用`knapsackGreedy`函数来解决贪心算法的背包问题了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值