C++ 优化子集和实现

C++ 优化子集和实现,c++,c,optimization,C++,C,Optimization,我正在使用下面的代码解决子集和问题的一个变体。这个问题需要从一个更大的集合(超集)生成11个整数的子集,并检查它是否匹配一个特定的值(endsum) #包括 #包括 #包括 int-endsum=0,supersetsize=0,done=0; int超集[]={1,30,10,7,11,27,3,5,6,50,45,32,25,67,13,37,19,52,18,9}; int-combo=0; int-SearchForPlayerArray(int-arr[],int-player){ 对

我正在使用下面的代码解决子集和问题的一个变体。这个问题需要从一个更大的集合(超集)生成11个整数的子集,并检查它是否匹配一个特定的值(endsum)

#包括
#包括
#包括
int-endsum=0,supersetsize=0,done=0;
int超集[]={1,30,10,7,11,27,3,5,6,50,45,32,25,67,13,37,19,52,18,9};
int-combo=0;
int-SearchForPlayerArray(int-arr[],int-player){

对于(int i=0;i只生成唯一子集的一种方法是按顺序添加超集中的元素,并使用一个附加参数
permute
(例如
supersetPos
)来指示您在超集中的位置。这将生成唯一的排序排列

编辑:AFAIK在样本上正确运行的代码:

#include <stdio.h>

int superset[] = {
 1, 30, 10, 7, 11,
 27, 3, 5, 6, 50,
 45, 32, 25, 67, 13,
 37, 19, 52, 18, 9
};
int supersetsize = 20;
int endsum = 110;
int done = 0;

int sumOfArray(int array[]) {
  int sum = 0;
  for(int i = 0; i < 11; i++)
      sum += array[i];
  return sum;
}

void permute(int subset[], int pos, int sspos) {

    if (pos == 11) { //is the current subset 11 ints long?
        if (sumOfArray(subset) == endsum) { //if the sum of the array matches the wanted sum, print
            for (int j=0; j<11; j++) {
                printf("%d ",subset[j]);
            }
            printf("\n");
            done = 1;
        }
        return;
    }
    for (int i=sspos; i<supersetsize; i++) {
        subset[pos] = superset[i];
        permute(subset,pos+1,i+1);
        if (done) { //when a correct solution has been found, stop recursion
            return;
        }
    }

}
int main() {
  int subset[11] = {0};
  permute(subset, 0, 0);
}
#包括
int超集[]={
1, 30, 10, 7, 11,
27, 3, 5, 6, 50,
45, 32, 25, 67, 13,
37, 19, 52, 18, 9
};
int supersetsize=20;
int-endsum=110;
int done=0;
int-sumOfArray(int数组[]){
整数和=0;
对于(int i=0;i<11;i++)
总和+=数组[i];
回报金额;
}
无效排列(int子集[],int位置,int sspos){
如果(pos==11){//当前子集是否为11整数长?
如果(sumOfArray(subset)==endsum){//如果数组的和与所需的和匹配,则打印

对于(int j=0;j只生成唯一子集的一种方法是按顺序添加超集中的元素,并使用一个附加参数
permute
(例如
supersetPos
)来指示您在超集中的位置。这将生成唯一的排序排列

编辑:AFAIK在样本上正确运行的代码:

#include <stdio.h>

int superset[] = {
 1, 30, 10, 7, 11,
 27, 3, 5, 6, 50,
 45, 32, 25, 67, 13,
 37, 19, 52, 18, 9
};
int supersetsize = 20;
int endsum = 110;
int done = 0;

int sumOfArray(int array[]) {
  int sum = 0;
  for(int i = 0; i < 11; i++)
      sum += array[i];
  return sum;
}

void permute(int subset[], int pos, int sspos) {

    if (pos == 11) { //is the current subset 11 ints long?
        if (sumOfArray(subset) == endsum) { //if the sum of the array matches the wanted sum, print
            for (int j=0; j<11; j++) {
                printf("%d ",subset[j]);
            }
            printf("\n");
            done = 1;
        }
        return;
    }
    for (int i=sspos; i<supersetsize; i++) {
        subset[pos] = superset[i];
        permute(subset,pos+1,i+1);
        if (done) { //when a correct solution has been found, stop recursion
            return;
        }
    }

}
int main() {
  int subset[11] = {0};
  permute(subset, 0, 0);
}
#包括
int超集[]={
1, 30, 10, 7, 11,
27, 3, 5, 6, 50,
45, 32, 25, 67, 13,
37, 19, 52, 18, 9
};
int supersetsize=20;
int-endsum=110;
int done=0;
int-sumOfArray(int数组[]){
整数和=0;
对于(int i=0;i<11;i++)
总和+=数组[i];
回报金额;
}
无效排列(int子集[],int位置,int sspos){
如果(pos==11){//当前子集是否为11整数长?
如果(sumOfArray(subset)==endsum){//如果数组的和与所需的和匹配,则打印

对于(int j=0;j我认为没有一种方法可以在比指数时间更好的时间内生成唯一的子集


要有效地求解子集和,您需要使用动态规划。有一些用于子集和的伪多项式时间算法可以这样工作。这可能会有所帮助。

我认为没有比指数时间更好的方法来生成唯一的子集

要有效地求解子集和,您需要使用动态规划。有一些用于子集和的伪多项式时间算法可以这样工作。这可能会有所帮助。

您可以尝试我的代码(我尝试只给出一个psudo代码,而不是完全解算您的家庭作业):

//数组是您从中查找的所有数字
//length是数组的数目
//pos是您要填充的插槽的位置
//max是您必须填充的插槽的名称(在您的情况下,因为您要填充11组,所以必须将该值设置为11)
//sum是迄今为止选定的所有值的总和
//searchbegin是可以从数组中选择的第一个元素(我使用此变量仅生成超集(数组)的子数组)
//target是您要查找的targetvalue。
void generate_all(int[]数组、int length、int pos、int max、int sum、int searchbegin、int target)
{
如果最大值=位置
如果总和=目标
printselectedresults();
对于i:searchbegin->length max+pos
if(和+数组[i]<目标)
{
增补结果(i);
生成_all(数组、长度、位置+1、最大值、和+数组[i]、i+1、目标);
从结果中删除(i);
}
}
有了所有这些信息,我认为您可以轻松地在目标语言中实现并使用这些代码

在我的函数中,生成的所有置换都是超集的子数组,因此不能生成两次置换,而且每个置换至少生成一次。

您可以尝试我的代码(我尝试只给出一个psudo代码,而不是完全解决您的家庭作业):

//数组是您从中查找的所有数字
//length是数组的数目
//pos是您要填充的插槽的位置
//max是您必须填充的插槽的名称(在您的情况下,因为您要填充11组,所以必须将该值设置为11)
//sum是迄今为止选定的所有值的总和
//searchbegin是可以从数组中选择的第一个元素(我使用此变量仅生成超集(数组)的子数组)
//target是您要查找的targetvalue。
void generate_all(int[]数组、int length、int pos、int max、int sum、int searchbegin、int target)
{
如果最大值=位置
如果总和=目标
printselectedresults();
对于i:searchbegin->length max+pos
if(和+数组[i]<目标)
{
增补结果(i);
生成_all(数组、长度、位置+1、最大值、和+数组[i]、i+1、目标);
从结果中删除(i);
}
}
有了所有这些信息,我认为您可以轻松地在目标语言中实现并使用这些代码


在我的函数中,生成的所有置换都是超集的子数组,因此不能生成两次置换,而且每个置换至少生成一次。

在次指数时间内,绝对没有办法生成唯一的子集,因为子集的数量是指数级的。但至少可以避免生成eve超指数时间内的Ry置换。在子指数时间内绝对没有生成唯一子集的方法,但是,在指数超时的情况下,至少可以避免产生每个置换。这是C++还是C?它像C一样臭,但技术上,它可以是C++,我猜。
// array is all the numbers you are looking from them
// length is the number of arrays
// pos is the position of the slot you are going to fill
// max is nomber of slots you have to fill (in your case since you are going for the 11 sets you have to set this value as 11
// sum is the sum of all the values selected until now
// searchbegin is the first element you can pick from your array (I'm using this variable to only generate subarrays of the superset (array))
// target is the targetvalue you are looking for.

void generate_all(int []array, int length, int pos,int max, int sum,int searchbegin,int target)
{
    if max = pos
        if sum = target
            printselectedresults();
    for i:searchbegin->length-max+pos
        if (sum + array[i] < target)
        {
            addtoresults(i);
            generate_all(array,length,pos+1,max,sum+array[i],i+1,target);
            removefromresults(i);
        }
}