diff --git a/codes/c/chapter_greedy/CMakeLists.txt b/codes/c/chapter_greedy/CMakeLists.txt index 3eb2b8eb1..7959b7d7c 100644 --- a/codes/c/chapter_greedy/CMakeLists.txt +++ b/codes/c/chapter_greedy/CMakeLists.txt @@ -1 +1,4 @@ add_executable(coin_change_greedy coin_change_greedy.c) +add_executable(fractional_knapsack fractional_knapsack.c) +add_executable(max_capacity fractional_knapmax_capacitysack.c) +add_executable(max_product_cutting max_product_cutting.c) diff --git a/codes/c/chapter_greedy/fractional_knapsack.c b/codes/c/chapter_greedy/fractional_knapsack.c new file mode 100644 index 000000000..a801b4e84 --- /dev/null +++ b/codes/c/chapter_greedy/fractional_knapsack.c @@ -0,0 +1,62 @@ +/** + * File: fractional_knapsack.c + * Created Time: 2023-09-14 + * Author: xianii (xianyi.xia@outlook.com) + */ + +#include "../utils/common.h" + +/* 物品 */ +struct item { + int w; // 物品重量 + int v; // 物品价值 +}; + +typedef struct item Item; + +/* 按照价值密度排序 */ +int sortByValueDensity(const void *a, const void *b) { + Item *t1 = (Item *)a; + Item *t2 = (Item *)b; + return (float)(t1->v) / t1->w < (float)(t2->v) / t2->w; +} + +/* 分数背包:贪心 */ +float fractionalKnapsack(int wgt[], int val[], int itemCount, int cap) { + // 创建物品列表,包含两个属性:重量、价值 + Item *items = malloc(sizeof(Item) * itemCount); + for (int i = 0; i < itemCount; i++) { + items[i] = (Item){.w = wgt[i], .v = val[i]}; + } + // 按照单位价值 item.v / item.w 从高到低进行排序 + qsort(items, (size_t)itemCount, sizeof(Item), sortByValueDensity); + // 循环贪心选择 + float res = 0.0; + for (int i = 0; i < itemCount; i++) { + if (items[i].w <= cap) { + // 若剩余容量充足,则将当前物品整个装进背包 + res += items[i].v; + cap -= items[i].w; + } else { + // 若剩余容量不足,则将当前物品的一部分装进背包 + res += (float)cap / items[i].w * items[i].v; + cap = 0; + break; + } + } + free(items); + return res; +} + +/* Driver Code */ +int main(void) { + int wgt[] = {10, 20, 30, 40, 50}; + int val[] = {50, 120, 150, 210, 240}; + int capacity = 50; + + // 贪心算法 + float res = fractionalKnapsack(wgt, val, sizeof(wgt) / sizeof(int), capacity); + printf("不超过背包容量的最大物品价值为 %0.2f\n", res); + + return 0; +} diff --git a/codes/c/chapter_greedy/max_capacity.c b/codes/c/chapter_greedy/max_capacity.c new file mode 100644 index 000000000..3b1dcb11b --- /dev/null +++ b/codes/c/chapter_greedy/max_capacity.c @@ -0,0 +1,43 @@ +/** + * File: max_capacity.c + * Created Time: 2023-09-15 + * Author: xianii (xianyi.xia@outlook.com) + */ + +#include "../utils/common.h" + +#define MIN(a, b) (a < b ? a : b) +#define MAX(a, b) (a > b ? a : b) + +/* 最大容量:贪心 */ +int maxCapacity(int ht[], int htLength) { + // 初始化 i, j 分列数组两端 + int i = 0; + int j = htLength - 1; + // 初始最大容量为 0 + int res = 0; + // 循环贪心选择,直至两板相遇 + while (i < j) { + // 更新最大容量 + int capacity = MIN(ht[i], ht[j]) * (j - i); + res = MAX(res, capacity); + // 向内移动短板 + if (ht[i] < ht[j]) { + i++; + } else { + j--; + } + } + return res; +} + +/* Driver Code */ +int main(void) { + int ht[] = {3, 8, 5, 2, 7, 7, 3, 4}; + + // 贪心算法 + int res = maxCapacity(ht, sizeof(ht) / sizeof(int)); + printf("最大容量为 %d\n", res); + + return 0; +} diff --git a/codes/c/chapter_greedy/max_product_cutting.c b/codes/c/chapter_greedy/max_product_cutting.c new file mode 100644 index 000000000..0278143c4 --- /dev/null +++ b/codes/c/chapter_greedy/max_product_cutting.c @@ -0,0 +1,38 @@ +/** + * File: max_product_cutting.c + * Created Time: 2023-09-15 + * Author: xianii (xianyi.xia@outlook.com) + */ + +#include "../utils/common.h" + +/* 最大切分乘积:贪心 */ +int maxProductCutting(int n) { + // 当 n <= 3 时,必须切分出一个 1 + if (n <= 3) { + return 1 * (n - 1); + } + // 贪心地切分出 3 ,a 为 3 的个数,b 为余数 + int a = n / 3; + int b = n % 3; + if (b == 1) { + // 当余数为 1 时,将一对 1 * 3 转化为 2 * 2 + return pow(3, a - 1) * 2 * 2; + } + if (b == 2) { + // 当余数为 2 时,不做处理 + return pow(3, a) * 2; + } + // 当余数为 0 时,不做处理 + return pow(3, a); +} + +/* Driver Code */ +int main(void) { + int n = 58; + // 贪心算法 + int res = maxProductCutting(n); + printf("最大切分乘积为 %d\n", res); + + return 0; +} diff --git a/codes/c/utils/common.h b/codes/c/utils/common.h index 91843b9da..7014cbb93 100644 --- a/codes/c/utils/common.h +++ b/codes/c/utils/common.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "list_node.h" #include "print_util.h"