gpt4 book ai didi

c - 对所有排列求和的函数

转载 作者:太空宇宙 更新时间:2023-11-04 03:22:46 25 4
gpt4 key购买 nike

前段时间我写了一个程序,打印给定数组的所有可能排列,甚至打印所有部分数组:

    #define MAXARRAY 32
#include <stdio.h>
void combinations(int array[], int temp[], int start, int end, int index, int r);

void print_combinations(int array[], int n, int r){
int temp[r];
combinations(array, temp, 0, n-1, 0, r);
}

void combinations(int array[], int temp[], int start, int end, int index, int r){
if (index == r){
for (int j=0; j<r; j++)
printf("%d ", temp[j]);
printf("\n");
return;
}

for (int i=start; i<=end && end-i+1 >= r-index; i++){
temp[index] = array[i];
combinations(array, temp, i+1, end, index+1, r);
}
}

int main(){
int array[MAXARRAY];
int r;
int n = sizeof(array)/sizeof(array[0]);
int i=MAXarray, j;
for(j=0;j<MAXARRAY;j++){
array[j]=j+1;
}
for(r=0;r<=i;r++)
print_combinations(array, n, r);
}

现在我正在尝试将此程序转换为执行以下操作:

我不想打印排列,而是想对所有排列求和并将总和与固定值进行比较,如果排列中的数字总和确实等于该固定值,它会增加计数器,所以最后我可以检查有多少排列总和等于该值。这是我现在想到的:

#define MAXARRAY 32
#include <stdio.h>
int combinations (int array[], int temp[], int start, int end, int index, int r);

void print_combinations (int array[], int n, int r){
int temp[r];
combinations(array, temp, 0, n-1, 0, r);
}

int combinations (int array[], int temp[], int start, int end, int index, int r){
int sum=0, counter=0;
if (index == r) {
for (int j=0; j<r; j++){
sum=sum+temp[j];
}
if(sum==264){
counter++;
}
}
for (int i=start; i<=end && end-i+1 >= r-index; i++){
temp[index] = array[i];
combinations(array, temp, i+1, end, index+1, r);
}
return counter;
}


int main()
{
int array[MAXARRAY];
int r;
int n = sizeof(array)/sizeof(array[0]);
int i=MAXARRAY, j;
for(j=0;j<MAXARRAY;j++){
array[j]=j+1;
}
for(r=0;r<=i;r++)
print_combinations(array, n, r);

我不知道如何正确地改变它以获得我想要的东西,确切地说我有点迷失了如何切换 void 函数来打印一个没有出现在函数中的计数器,我不确定是否我可以轻松地“改变”这段代码以获得我想要的,或者我只需要编写全新的函数。

最佳答案

您想知道有多少种方法可以从给定的集合中挑选数字,以便它们总和达到给定的目标值。您似乎以错误的方式处理这个问题,因为您混淆了排列和组合。

Permutations是一组具有固定大小 n 的项目的不同排列,如果所有项目都不同,则可能的排列数为 n!。这在这里没有用,因为求和是可交换的;操作数的顺序无关紧要。

Combinations告诉你一组中的哪些项目包括在内,哪些不包括。这就是你想要的。幸运的是,只有 2ⁿ 种可能的方法可以从一组 n 中挑选项目,包括所有项目或没有。

你也可以递归地解决这个问题。每个递归级别处理一个项目,您可以选择包含或不包含它。对于这些项目,您将获得以下决策树:

                                  0
/ \
0 1
/ \ / \
0 2 0 2
/ \ / \ / \ / \
0 3 0 3 0 3 0 3

sum 0 3 2 5 1 4 3 6

走左边的分支省略一个项目,走右边的分支包括它。这将为您提供两次 3 的总和以及一次从 0 到 6 的所有其他总和。有 8 条可能的路径。

下面的程序是这样做的:

#include <stdlib.h>
#include <stdio.h>

#define N 32
#define TARGET 264

/*
* Print the summands
*/
void print(const int a[], int n)
{
int i;

for (i = 0; i < n; i++) {
if (i) printf(" + ");
printf("%d", a[i]);
}

puts("");
}

/*
* Actual recursive combination function
*/
size_t combine_r(const int pool[], // summand pool
int res[], // currently included items
int max, // length of pool
int n, // length of res
int i, // current item's index in pool
int sum, // running sum
int target) // desired target
{
int count = 0;

if (i == max) {
if (sum == target) {
//print(res, n);
count++;
}
} else {
count += combine_r(pool, res, max, n, i + 1, sum, target);

res[n++] = pool[i];
count += combine_r(pool, res, max, n, i + 1,
sum + pool[i], target);
}

return count;
}

/*
* Interface function for the recursive function.
*/
size_t combine(const int pool[], int n, int target)
{
int res[n];

return combine_r(pool, res, n, 0, 0, 0, target);
}



int main()
{
int pool[N];
size_t n;
int i;

for (i = 0; i < N; i++) pool[i] = i + 1;

n = combine(pool, N, TARGET);
printf("%zu combinations.\n", n);

return 0;
}

如果总和等于目标,该函数会沿着每条路径进行记录并记录一次命中。当您从递归返回并沿着树向上移动时,会返回每个子树中的命中数,以便您在根级别获得总命中数。

函数 combine 只是实际递归函数的前端,因此您不必从 main 传递那么多零。递归函数的参数可能会更优雅地减少和组织。 (它们中的两个存在只是因为在 C 中你必须将数组的长度传递给 i。如果你只是想计算可能性,你可以去掉 resn,它只是用来打印数组。)

关于c - 对所有排列求和的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43928357/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com