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

C++ 计算N个整数组合的绝对值,c++,C++,对于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"

对于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);
         }
    }
}
现在我的任务是计算所有组合的绝对值,如:

对于组合[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 --;
}
while(位置>0)
{
对于(int a=0;a
但我觉得我做错了什么,因为所有的套票都没有印出来。虽然我觉得我快完成了,但我无法构建逻辑框架。以下是我的整个计划:

#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 = %d\n" , 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 = '\0';
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 = %llu\n" , end - start);
return 0;
}
#包括
#包括
#包括
#包括
#包括
int*a;
int*a1;
INTR;
INTC;
无符号长整数no=1;
int stoi(字符*变量)
{
int n1=0;
int n2=0;
int n3=0;
字符符号=0;
while(*var)
{
if(isspace(*var))
{
var++;
继续;
}
而(*var>='0'&&*var 0)
{
对于(int a=0;a0;j--)
如果(j==c)
sprintf(p,“%d”,t[j]);
其他的
sprintf(p,“%s,%d”,p,t[j]);
印刷联合体(p);
}
其他的
for(int i=n;i对于(int i=0;i您尝试执行的操作非常类似于枚举从“N选择1”到“N选择N”的所有组合。我建议您在google中搜索“枚举组合”

以下是我找到的链接之一:


这是一个如何操作的逻辑。打印大小为
n-1
的所有二进制数字,其中
n
是相应组合的大小(元素数)。例如,要对组合执行您想要执行的操作[1,2,3,4],请创建
3
的所有二进制组合(n-1=3,此处n=4个元素)。即


现在在for循环中运行你的组合,每当你找到一个
0
做加法,每当你找到
1
做减法。例如
000
将意味着
1+2+3+4
101
将意味着
1-2+3-4

有一种更简单的方法来做什么。你想把一个向量o相加f N整数:

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

其中kx=-1,0,+1


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

一些@SteveC解决方案的代码:

#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, "");
}

是的,我能够通过create_print_combines方法coded生成组合-我的问题是我无法获得逻辑来打印所有组合的绝对和:比如Combi 1,2,3:1+2+3,1+2-3,1-2+3,1-2-3。我的逻辑会因较大的值而中断,比如n=10;只需在顶部传递n,在递归调用中传递n-1。不需要Rx.还需要打印结果的绝对值。@SteveC,+1分。请随意将我的代码复制到您的答案中,包括这些更改。您应该得到接受的答案!我将在接下来的几个小时内离线。我想了解您在逻辑上提出的概念/方法,以及映射到它的所需代码实现[如下所述]。我认为这些是我需要掌握的技能。请以明确的方式提供一些输入,是否有一些细节可以讨论。我也看到过类似O(lonN)…等概念,但确实不太了解。你从向量[1,2,3,…N]开始取N个元素的所有组合,相当于乘以0或+1。然后取所有+1元素,然后进行加法或减法,这与乘以+1或-1是一样的。我注意到你可以一步完成。
#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 = %d\n" , 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 = '\0';
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 = %llu\n" , end - start);
return 0;
}
when n = 3, the possible combinations are:
000
001
010
011
100
101
110
111
#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