在 C 中为所有可能的排列设计一个算法,包括零[关闭]
Posted
技术标签:
【中文标题】在 C 中为所有可能的排列设计一个算法,包括零[关闭]【英文标题】:Devising an algorithm in C for all possible permutations, including zero [closed] 【发布时间】:2014-05-24 18:42:01 【问题描述】:我正在尝试用 C 语言设计和编写一种算法,以提供一个表格,列出 5 个不同组件的不同百分比。我需要得到一个看起来像这样的表格:
糖(50%)......盐(20%)......胡椒(10%)......辣椒(10%)......辣椒(10%) 糖(50%)......盐(50%)......胡椒(00%)......辣椒(00%)......辣椒(00%) 糖(00%)......盐(100%)......胡椒(00%)......辣椒(00%)......辣椒(00%) 糖(10%)......盐(00%)......胡椒(90%)......辣椒(00%)......辣椒(00%)
我需要捕获所有可能的排列,并注意 0% 是一个有效的排列,如上所示。所有排列之和必须始终为 100%。
我意识到以 1% 的粒度列出所有可能的排列意味着大量的排列,所以我希望能够将一个变量传递给我的函数来定义粒度级别;粒度越高,表项数越少。
我已经查看了许多与此类似的 SO 问题,但我找不到一个处理以下情况的问题:1)订单不重要 2)可以排除物品(在我的情况下,这意味着item 的值为 0); 3) 这个例子是用 C 语言编写的。
[PS:我已经通过使用食物来简化事情,但这不是家庭作业……请参阅我的其他帖子。]
所以,我的问题是,我该如何编码?事实上,我曾尝试使用递归循环对此进行编码:
int variations[] = 10, 20, 30, 40, 50, 60, 70, 80, 90 ;
char names[][10] = "sugar", "spice", "pepper", "cayenne", "salt", "" );
int componentCount = 5;
for (int i = 0; i < componentCount; ++i)
for (int j = 1; j < componentCount; ++j)
for (int k = 2; k < compoentCount; ++k)
for (int l = 3; l < componentCount; ++l)
for (int m = 4; m < componentCount; ++m)
for (int x = 0; x < componentCount; ++x)
printf("%s=%d", names[x], variations[x]);
但这并不能满足我在捕获所有变化方面需要它做的事情,而且我之前没有发布这个,因为我认为我需要采取完全不同的方法,因此我的问题是:这怎么可能完成了吗?
【问题讨论】:
它可能不是为了家庭作业,但你没有表现出任何努力来回答你的问题。 也没有问题。那里没有?
。这只是一个要求列表。
这个问题没有问题。你所做的只是列出一个事实清单。您正在尝试设计一种算法。你不知道怎么做。这些都是事实。你有什么问题?尝试用关于某些特定代码行的特定技术问题来表达您的问题。
如果您的问题是“我如何开始解决我不知道如何解决的问题?”这对 *** 来说不是一个好问题,但我已经准备了一个页面来提供一种技术。 ericlippert.com/2014/03/21/find-a-simpler-problem
你确定你知道什么是递归方法吗?你说这是一个“递归循环”,但实际上它是一个嵌套循环。你可以用递归解决这个问题,但递归与嵌套循环有很大不同。
【参考方案1】:
你可以用递归来解决这个问题。请记住,每个递归函数都有以下模式:
我的情况很简单吗?如果是,请解决简单的问题。 我的情况更复杂吗?如果是这样,请将问题分解为一个或多个更简单的问题。 递归解决每个更简单的问题。 现在将更简单问题的解决方案组合成更难问题的解决方案。总是从最简单的问题开始。你最简单的问题是什么?
我有一件物品必须占总数的 x%。解决方案是:该项目占总数的 x%。
现在假设您有 n 项必须占总数的 x%。你怎么做呢?把它分解成更简单的问题:
假设项目 1 占总数的 0%。现在我有 n-1 个项目,占总数的 x%。列出所有这样做的方法。 假设项目 1 占总数的 5%。现在我有 n-1 个项目,占总数的 x-5%。列出所有这样做的方法。 ... 假设项目 1 占总数的 x%。现在我有 n-1 个项目,占总数的 0%。列出所有这样做的方法。你已经完成了。
现在把它翻译成代码。
【讨论】:
【参考方案2】:让我们根据粒度对其进行重新表述:您想要的本质上是枚举将 N 表示为 K 个非负整数之和的方法。这里,N 是粒度(对于 5% 的增量,N 将是 100% / 5% = 20),K 是项目数。
在这样的公式中,只需要一个带有参数 k(从 0 到 K-1 的索引)和 n(N 的剩余部分)的递归函数,使用类似 C 的伪代码:
int a [MAX_K];
void fun (int k, int n)
int i;
if (k < 0)
if (n == 0)
<print - or otherwise use - array a>
return;
for (i = 0; i <= n; i++)
a[k] = i; // run the branch where k-th item gets i/N of the total sum
fun (k - 1, n - i);
...
<call it as "fun (K - 1, N)">
如果全局变量不是一个选项,您可以在递归中随身携带指向数组a
的指针。
【讨论】:
是的,全局变量很好。感谢您的帮助。 @user994179:抱歉,代码总和为 if (n == 0) ...”)。【参考方案3】:定义粒度级别的唯一合理方法是 1/n,其中 n 是一个正整数。 IE。您想将某些 n 的百分比拆分为 1/n 的倍数。否则,如果您只希望所有正百分比都大于 1/n,您将获得无限多的可能性。查看“星条”结构,了解如何将整数 n 拆分为 k 个非负部分。您将看到可能性数量的答案是(n+k-1 选择 k-1),并查看从 1 到 n+k-1 范围内的 k-1 个数字的每个选择如何导致唯一的百分比分配在您尝试生成的组合中。网上也有关于如何从一组中生成特定尺寸的所有组合的参考资料。
【讨论】:
以上是关于在 C 中为所有可能的排列设计一个算法,包括零[关闭]的主要内容,如果未能解决你的问题,请参考以下文章