2011-12-19 70 views
0

对于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 = %llu\n" , end - start); 
    return 0; 
} 

给我组合像N = 4:

输入一个正整数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] 

现在我的任务就是喜欢像所有组合的绝对值:

对于组合[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 --; 
} 

但我beleiev我做的事情错了,因为没有得到所有打印设置。尽管我觉得我已接近完成,但我无法确定逻辑。下面是我的整个程序:

#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; 
} 

根据程序逻辑我计算组合作为字符串和生成表达式的绝对值。

回答

0

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

输出开始:

+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 
+1

只需在顶部传递N,在递归调用中传递N-1。不需要x。还需要在结果上打印绝对值。 – 2011-12-19 18:52:39

+0

@SteveC,+1分优点。随意将我的代码复制到您的答案中,包括这些更改。你应该得到接受的答案!无论如何,我将在接下来的几个小时内离线。 – 2011-12-19 18:56:01

+1

我确认你的解决方案。看起来不错。 – 2011-12-19 19:25:18

0

你所要做的与列举所有组合从“N选择1”到“N选择N”非常相似。我建议你在谷歌下的术语“枚举组合”

这里是我发现的一个环节搜索:

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

+0

是的,我能够产生通过create_print_combinations方法编码组合 - 我的问题是,我不能够以获得打印所有组合的绝对和的逻辑:类似于Combi 1,2,3:1 + 2 + 3,1 + 2-3,1-2 + 3,1-2-3。我的逻辑打破了一个更大的值,n = 10; – Prakash 2011-12-19 06:14:19

0

这里是如何做到这一点逻辑。打印所有尺寸为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 

现在运行在您的组合为循环和里面,只要你找到一个0做加法,只要你找到1做减法。例如,000意味着1+2+3+4101意味着1-2+3-4

1

有一个更简单的方法来处理你在做什么。要添加了N个整数的向量:

[1 * K1,2 * K2,3 * ... K3 N *千牛]

其中KX = -1,0,+ 1。

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

+0

我想了解您在逻辑上想出的概念/方法,并将所需的代码实现映射到它[如下所述]。我认为这些是我需要掌握的技能。请以明确的方式提供一些意见,是否有一些细节可以谈论它。我也看到了O(lonN)等概念,但实际上并不了解它。 – Prakash 2011-12-20 13:14:37

+0

您以向量[1,2,3,... N]开头 您将N个元素的所有组合相当于乘以0或+1。然后,您将所有+1元素加上或减去,这与乘以+1或-1相同。我只注意到你可以一步到位。 – 2011-12-20 15:31:46