计算N个整数组合的绝对值

Compute Absolute values of N integer combinations Combinations

本文关键字:绝对值 组合 整数 计算      更新时间:2023-10-16

对于N个数(a..N),我正在用以下方法寻找所有组合的集合:

void create_print_combinations(int *t, int x, int n) {
    if(x == 0) {
        char p [2 * r + 2];
        memset (p, 0, 2 * r +2);
        for (int j=c;j>0;j--)
            if(j == c)
                sprintf(p, "%d", t[j]);
            else
                sprintf(p, "%s,%d", p,t[j]);
            print_combi(p);
    } else {
         for (int i= n; i < r; i++) {
             t[x] = a[i];
             create_print_combinations(t, x-1, i+1);
         }
    }
}

调用函数如下:

int main() {
    unsigned long int start=0, end=0;
    printf ("nEnter the a positive integer N:");
    scanf("%d", &r);
    start=time(NULL);
    a = new int[r];
    for (int i = 0;i<r;i++)
    a[i]=i+1;
    for(int j=1;j<=r;j++) {
        a1 = new int[j];
        c=j;
        create_print_combinations(a1, c, 0);
        delete[] a1;
    }
    end=time(NULL);
    printf("Total time taken = %llun" , end - start);
    return 0;
}

给出如下组合:

输入正整数N:4

Combo : [1]
Combo : [2]
Combo : [3]
Combo : [4]
Combo : [1,2]
Combo : [1,3]
Combo : [1,4]
Combo : [2,3]
Combo : [2,4]
Combo : [3,4]
Combo : [1,2,3]
Combo : [1,2,4]
Combo : [1,3,4]
Combo : [2,3,4]
Combo : [1,2,3,4]

现在我的任务是查找所有组合的绝对值,例如:

对于Combo[1,2,3,4],应该是:

1+2+3+4 = abs(1+2+3+4)
1+2+3-4 = abs(1+2+3-4)
1+2-3-4 = ..
1-2-3+4 = ...

等等

我正在尝试以下逻辑:

while(pos > 0)
{
for(int a=0; a < i; a++)
{
if(a==0)
sprintf(p,"%d", t[a]);
else if(a == pos)
sprintf(p,"%s%c%d",p, minus, t[a]);
else
sprintf(p,"%s%c%d",p, plus, t[a]);
}
print(p);
memset (p , 0, 2 * r +2);
pos --;
}

但是我认为我做错了什么,因为所有的集合都没有打印出来。虽然我觉得快要完成了,但我还是不能把逻辑框定下来。下面是我的整个程序:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
int *a;
int *a1;
int r;
int c;
unsigned long int no =1;
int stoi(char *var)
{
int n1 = 0;
int n2 = 0;
int n3 = 0;
char sign=0;
while(*var)
{
if(isspace(*var))
{
var++;
continue;
}
while(*var >= '0' && *var <= '9')
{
n1=(n1*10) + (*var - '0');
var++;
continue;
}
if(sign == '+')
{
n2=n2+n1;
n1=0;
}
else if(sign == '-')
{
n2=n2 - n1;
n1=0;
}
if(*var == '+' || *var == '-')
{
if(sign == 0)
{
n2=n1;
n1=0;
}
sign = *var;
}
var++;
}
if(sign == 0)
return abs(n1);
return abs(n2);
}
void print(char* var)
{
printf("[Combo %llu.] %s = %dn" , no++, var, stoi(var));
}
void print_combi(char * a)
{
int t[c];
char *x = NULL;
char *y = a;
int i=0;
while((x=strchr(y, ',')) != NULL)
{
*x = '';
t[i++]=atoi(y);
y=x+1;
}
t[i++]=atoi(y);
int count =0;
int loop = 0;
char p [2 * r + 2];
memset (p , 0, 2 * r +2);
char plus = '+';
char minus = '-';
for(int k=0;k<2;k++)
{
if(k==1)
{
plus =  '-';
minus = '+';
}
if(i>1)
{
for(int a=0; a < i; a++)
{
if(a==0)
sprintf(p,"%d", t[a]);
else
sprintf(p,"%s%c%d",p, plus, t[a]);
}
}
else if(i==1)
{
sprintf(p,"%d", t[i-1]);
print(p);
break;
}
print(p);
memset (p , 0, 2 * r +2);
if(i==2)
continue;
if(i==3 && k ==1)
break;
int pos = i-1;
while(pos > 0)
{
for(int a=0; a < i; a++)
{
if(a==0)
sprintf(p,"%d", t[a]);
else if(a == pos)
sprintf(p,"%s%c%d",p, minus, t[a]);
else
sprintf(p,"%s%c%d",p, plus, t[a]);
}
print(p);
memset (p , 0, 2 * r +2);
pos --;
}
}
}
void create_print_combinations(int *t, int x, int n)
{
if(x == 0)
{
char p [2 * r + 2];
memset (p, 0, 2 * r +2);
for (int j=c;j>0;j--)
if(j == c)
sprintf(p, "%d", t[j]);
else
sprintf(p, "%s,%d", p,t[j]);
print_combi(p);
}
else
for (int i= n; i < r; i++)
{
t[x] = a[i];
create_print_combinations(t, x-1, i+1);
}
}
int main()
{
unsigned long int start=0, end=0;
printf ("nEnter the a positive integer N:");
scanf("%d", &r);
start=time(NULL);
a = new int[r];
for (int i = 0;i<r;i++)
a[i]=i+1;
for(int j=1;j<=r;j++)
{
a1 = new int[j];
c=j;
create_print_combinations(a1, c, 0);
delete[] a1;
}
end=time(NULL);
printf("Total time taken = %llun" , end - start);
return 0;
}

根据程序逻辑,我正在将组合计算为字符串并生成表达式的绝对值。

有一种更简单的方法。你想要加一个N个整数的向量:

[1*k1, 2*k2, 3*k3,…]N * kN)

where kx = - 1,0, +1

对于x=1..N, kx有3^N种组合

@ steve的解决方案:

#include <iostream>
#include <sstream>
using namespace std;
void print_sum(int N, int sum_so_far, string as_a_string) {
        if(N) {
                ostringstream oss; oss << N;
                print_sum(N-1, sum_so_far+N, as_a_string + "+" + oss.str() + " ");
                print_sum(N-1, sum_so_far-N, as_a_string + "-" + oss.str() + " ");
                print_sum(N-1, sum_so_far, as_a_string);
        } else {  
                if (sum_so_far < 0) sum_so_far *= -1;
                cout << as_a_string << "t= " << sum_so_far << endl;            }
}
int main() {
        print_sum(4, 0, "");
}

输出开始:

+4 +3 +2 +1     = 10
+4 +3 +2 -1     = 8
+4 +3 +2        = 9
+4 +3 -2 +1     = 6
+4 +3 -2 -1     = 4
+4 +3 -2        = 5
+4 +3 +1        = 8
+4 +3 -1        = 6
# .. and so on

你要做的是非常类似于枚举从"N选1"到"N选N"的所有组合。我建议你用google搜索"枚举组合"

这是我找到的一个链接:

http://www.codeproject.com/KB/recipes/CombC.aspx

下面是如何做到这一点的逻辑。打印大小为n-1的所有二进制数字,其中n是各自组合的大小(元素数)。例如,要为组合[1,2,3,4]做你想做的事情,创建3的所有二进制组合(n-1 = 3,这里n = 4个元素)。例如

when n = 3, the possible combinations are:
000
001
010
011
100
101
110
111

现在在for循环中运行你的组合,每当你发现0时,就在里面做加法,每当你发现1时,就做减法。例如,000表示1+2+3+4, 101表示1-2+3-4