这是我编写的代码:-
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int ctr = 0;
void partition(int arr[], int n) {
int i, j, k = 0, r, in = 0, te, flag = 0;
int *sum;
sum = (int*)malloc(sizeof(int) * pow(2, n));
for (i = 0; i < pow(2, n); i++) {
printf("{");
for (j = 0; j < n; j++) {
if (i & (1 << j)) {
printf("%d ", arr[j]);
sum[k] = sum[k] + arr[j];
}
}
k++;
printf("}");
printf("\n");
}
printf("\n \n");
int *temp;
for (k = 0; k < pow(2, n) - 1; k++) {
in = 0;
temp = (int*)malloc(sizeof(int));
for (r = k + 1; r < pow(2, n); r++) {
if (sum[k] == sum[r]) {
printf("\n Printing solution for sum %d", sum[k]);
for (i = 0; i < pow(2, n); i++) {
if (i == k || i == r) {
printf("{");
for (j = 0; j < n; j++) {
if (i & 1 << j) {
for (te = 0; te < in; te++) { //Disjointness
if (temp[te] == arr[j])
flag = 1;
}
if (flag == 1)
break;
temp[in++] = arr[j];
temp = (int*)realloc(temp, sizeof(int));
printf("%d ", arr[j]);
}
}
printf("}");
printf("\n");
}
}
break;
}
}
free(temp);
}
}
void main() {
int *arr, n, i;
printf("\n Enter the number of elements in the set \n");
scanf("%d", &n);
arr = (int*)malloc(sizeof(int) * n);
printf("\n Enter the set elements \n");
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
partition(arr, n);
}
它非常适合输入{1,2,3}
。对于{1,2,3,4}
,它也可以提供正确的输出。
对于{1,2,3,4}
,输出为:
Printing solution for sum 3{1 2 }
{3 }
Printing solution for sum 4{1 3 }
{4 }
Printing solution for sum 5{2 3 }
{1 4 }
Printing solution for sum 6{1 2 3 }
{}
Printing solution for sum 7{}
{}
但是如果输入为{1,5,11,5},则输出为:
Printing solution for sum 5{5 }
{}
Printing solution for sum 6{}
{}
Printing solution for sum 11{}
{}
Printing solution for sum 16{}
{}
Printing solution for sum 17{}
{}
由于{1,5,5}
和{11}
是解决方案,因此在这种情况下,预期输出应为Printing Solution for sum 11 {1,5,5} and {11}
,但不会显示出来。
有什么问题,我该如何解决?
答案 0 :(得分:1)
您可能会发现以下内容为起点。该示例程序要做的是获取一组值,然后生成尽可能不相交的子集,其中两个子集之间每个子集的元素之和相等。
我不确定这是否真的回答了您的问题。规定的要求很宽松。您提供的源代码无法使用Visual Studio进行编译,并且在纠正了一些基本的编译错误后,导致程序崩溃。我也发现您的示例输出令人困惑。
此程序创建的不相交子集的标准为:
源代码如下。这来自单个C源代码文件,该文件是Visual Studio C ++解决方案的一部分,其中C ++ main()
调用mymain2()
的C源代码入口点。我这样做是因为对我来说更容易。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct {
int *pSet; // array of values. array is malloced when max number is known.
int nSetMax; // max number of array elements, amount malloced.
int nSetCur; // current number of in use array elements.
} SetType;
static void generateSet (int i, int arr[], int n, SetType *temp)
{
int j;
temp->nSetCur = 0;
for (j = 0; j < n; j++)
{
if ( i & (1 << j))
{
int te;
int flag = 0;
for (te = 0; te < temp->nSetCur; te++)
{
// we compute disjoint property by the order of the elements in
// the set using element index in order to allow duplicate values per
// request of the question. Exampe 1, 5, 11, 5 as list of values.
if (temp->pSet[te] == j)
flag = 1;
}
if (flag == 1)
continue;
temp->pSet[temp->nSetCur] = j;
temp->nSetCur++;
}
}
}
static void printItems (int arr[], const SetType temp)
{
if (temp.nSetCur > 0) {
int j;
int sum = 0;
printf(" {");
for (j = 0; j < temp.nSetCur; j++) {
printf("%2d ", arr[temp.pSet[j]]);
sum += arr[temp.pSet[j]];
}
printf("} = %3d\n", sum);
} else
printf (" {}\n");
}
// determine if the two sets are disjoint by comparing the element indexes
// of the elements in each subset. the element index is the position of the
// subset element in the set from which the subset was drawn.
static int checkSetsByIndex (const SetType tempI, const SetType tempR)
{
int i;
for (i = 0; i < tempI.nSetCur; i++) {
int j;
for (j = 0; j < tempR.nSetCur; j++) {
if (tempI.pSet[i] == tempR.pSet[j])
return 0;
}
}
return 1;
}
// determine if the two sets are disjoint by comparing the element values
// of the elements in each subset. the element value is the value of the
// subset element in the set from which the subset was drawn.
// we may have duplicate values but as long as they are not in two different
// subsets then we allow it.
static int checkSetsByValue (int arr[], const SetType tempI, const SetType tempR)
{
int i;
#if 1
// following code does a check that the two sets are disjoint by value
// meaning they do not share any values. however a set may have multiple
// elements with the same value.
// if not needed then you can turn it off with Preprocessor check.
for (i = 0; i < tempI.nSetCur; i++) {
int j;
for (j = 0; j < tempR.nSetCur; j++) {
if (arr[tempI.pSet[i]] == arr[tempR.pSet[j]])
return 0;
}
}
#endif
return 1;
}
static void partition(int arr[], int n)
{
int i;
int iPow2n = pow(2, n);
int *sum = calloc(iPow2n, sizeof(int));
printf ("Generate and list sums\n");
for(i = 0; i < iPow2n; i++)
{
int j;
printf(" {");
for (j = 0; j < n; j++)
{
if (i & (1 << j))
{
printf("%2d ", arr[j]);
sum[i] = sum[i] + arr[j];
}
}
printf("} = %3d\n", sum[i]);
}
printf("\n\nGenerate list of disjoint sets for each sum.\n");
for (i = 0; i < iPow2n - 1; i++)
{
int r;
SetType tempI = {calloc(iPow2n, sizeof(SetType)), iPow2n, 0};
SetType tempR = {calloc(iPow2n, sizeof(SetType)), iPow2n, 0};
for(r = i + 1; r < iPow2n; r++)
{
if(sum[i] == sum[r])
{
generateSet (i, arr, n, &tempI);
generateSet (r, arr, n, &tempR);
// check disjoint subsets by looking at the index of the
// subset elements where the index is the index of the original
// set from which the subset is drawn.
if (checkSetsByIndex (tempI, tempR)) {
// check that the two subsets are disjoint by element values
// as well. this means that while a subset may have duplicate
// values, the elements of each subset must be disjoint can not
// have elements whose values are the same.
// so if we have a set {1, 5, 11, 5} then subsets of
// {5}, {5} is invalid but {1, 5, 5}, {11} is valid.
if (checkSetsByValue (arr, tempI, tempR)) {
printf("\n Printing solution for sum %d\n", sum[i]);
printItems (arr, tempI);
printItems (arr, tempR);
break;
}
}
}
}
free(tempI.pSet);
free(tempR.pSet);
}
}
int mymain2(void)
{
int n;
printf("\n Enter the number of elements in the set \n");
scanf("%d",&n);
if (n > 0) {
int i;
int *arr = malloc(sizeof(int) * n);
printf("\n Enter the set elements \n");
for (i = 0; i < n; i++)
{
scanf("%d",&arr[i]);
}
partition(arr,n);
free (arr);
}
return 0;
}
对于元素为{1、2、3、4}的4个值的集合,它将生成以下输出:
Enter the number of elements in the set
4
Enter the set elements
1 2 3 4
Generate and list sums
{} = 0
{ 1 } = 1
{ 2 } = 2
{ 1 2 } = 3
{ 3 } = 3
{ 1 3 } = 4
{ 2 3 } = 5
{ 1 2 3 } = 6
{ 4 } = 4
{ 1 4 } = 5
{ 2 4 } = 6
{ 1 2 4 } = 7
{ 3 4 } = 7
{ 1 3 4 } = 8
{ 2 3 4 } = 9
{ 1 2 3 4 } = 10
Generate list of disjoint sets for each sum.
Printing solution for sum 3
{ 1 2 } = 3
{ 3 } = 3
Printing solution for sum 4
{ 1 3 } = 4
{ 4 } = 4
Printing solution for sum 5
{ 2 3 } = 5
{ 1 4 } = 5
对于一组4个值{1、5、11、5},它将生成以下输出:
Enter the number of elements in the set
4
Enter the set elements
1 5 11 5
Generate and list sums
{} = 0
{ 1 } = 1
{ 5 } = 5
{ 1 5 } = 6
{11 } = 11
{ 1 11 } = 12
{ 5 11 } = 16
{ 1 5 11 } = 17
{ 5 } = 5
{ 1 5 } = 6
{ 5 5 } = 10
{ 1 5 5 } = 11
{11 5 } = 16
{ 1 11 5 } = 17
{ 5 11 5 } = 21
{ 1 5 11 5 } = 22
Generate list of disjoint sets for each sum.
Printing solution for sum 11
{11 } = 11
{ 1 5 5 } = 11
对于一组5个值{1、2、3、4、5},它将生成以下输出:
Enter the number of elements in the set
5
Enter the set elements
1 2 3 4 5
Generate and list sums
{} = 0
{ 1 } = 1
{ 2 } = 2
{ 1 2 } = 3
{ 3 } = 3
{ 1 3 } = 4
{ 2 3 } = 5
{ 1 2 3 } = 6
{ 4 } = 4
{ 1 4 } = 5
{ 2 4 } = 6
{ 1 2 4 } = 7
{ 3 4 } = 7
{ 1 3 4 } = 8
{ 2 3 4 } = 9
{ 1 2 3 4 } = 10
{ 5 } = 5
{ 1 5 } = 6
{ 2 5 } = 7
{ 1 2 5 } = 8
{ 3 5 } = 8
{ 1 3 5 } = 9
{ 2 3 5 } = 10
{ 1 2 3 5 } = 11
{ 4 5 } = 9
{ 1 4 5 } = 10
{ 2 4 5 } = 11
{ 1 2 4 5 } = 12
{ 3 4 5 } = 12
{ 1 3 4 5 } = 13
{ 2 3 4 5 } = 14
{ 1 2 3 4 5 } = 15
Generate list of disjoint sets for each sum.
Printing solution for sum 3
{ 1 2 } = 3
{ 3 } = 3
Printing solution for sum 4
{ 1 3 } = 4
{ 4 } = 4
Printing solution for sum 5
{ 2 3 } = 5
{ 1 4 } = 5
Printing solution for sum 5
{ 1 4 } = 5
{ 5 } = 5
Printing solution for sum 6
{ 2 4 } = 6
{ 1 5 } = 6
Printing solution for sum 7
{ 3 4 } = 7
{ 2 5 } = 7
答案 1 :(得分:1)
您的算法太复杂。您从正确的路径开始,计算集合的所有子集的总和,但没有正确计算所有可能的不相交的子集,以尝试找到具有相同总和的子集。
这是一种更简单的方法:
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
struct s { int sig, sum; };
int compare(const void *p1, const void *p2) {
int sum1 = ((const struct s*)p1)->sum;
int sum2 = ((const struct s*)p2)->sum;
return (sum1 > sum2) - (sum1 < sum2);
}
void print_set(int arr[], size_t sig) {
printf("{");
while (sig) {
if (sig & 1)
printf(" %d", *arr);
arr++;
sig >>= 1;
}
printf(" } ");
}
void partition(int arr[], int n) {
size_t i, j, count = 1ULL << n;
struct s *array = calloc(sizeof(*array), count);
int b, sum;
if (array != NULL) {
for (i = 1; i < count; i++) {
sum = 0;
for (b = 0; b < n; b++) {
if (i & (1ULL << b))
sum += arr[b];
}
array[i].sig = i;
array[i].sum = sum;
}
qsort(array, count, sizeof(*array), compare);
for (i = 0; i < count; i++) {
for (j = i + 1; j < count && array[i].sum == array[j].sum; j++) {
if ((array[i].sig & array[j].sig) == 0) {
printf("solution with sum=%d: ", array[i].sum);
print_set(arr, array[i].sig);
print_set(arr, array[j].sig);
printf("\n");
}
}
}
free(array);
}
}
int main() {
int *arr, n, i;
printf("Enter the number of elements in the set: ");
if (scanf("%d", &n) == 1) {
arr = (int*)malloc(sizeof(int) * n);
if (arr != NULL) {
printf("Enter the set elements: ");
for (i = 0; i < n; i++) {
if (scanf("%d", &arr[i]) != 1)
return 1;
}
partition(arr, n);
free(arr);
}
}
return 0;
}
输出:
Enter the number of elements in the set: 3
Enter the set elements: 1 2 3
solution with sum=3: { 3 } { 1 2 }
Enter the number of elements in the set: 4
Enter the set elements: 1 2 3 4
solution with sum=3: { 1 2 } { 3 }
solution with sum=4: { 4 } { 1 3 }
solution with sum=5: { 2 3 } { 1 4 }
Enter the number of elements in the set: 4
Enter the set elements: 1 5 11 5
solution with sum=5: { 5 } { 5 }
solution with sum=11: { 11 } { 1 5 5 }