c或c+中为负值的子集和+;
我有这段代码用于查找正值的子集和,我搜索的每一个地方都只看到正整数或高级java编写的程序。我想知道如何实现我的C程序可以处理负数。实际上,我想让它找到0的和。我有个主意c或c+中为负值的子集和+;,c,algorithm,subset-sum,C,Algorithm,Subset Sum,我有这段代码用于查找正值的子集和,我搜索的每一个地方都只看到正整数或高级java编写的程序。我想知道如何实现我的C程序可以处理负数。实际上,我想让它找到0的和。我有个主意 取集合中的最小值,称之为k 通过绝对值k添加集合中的每个元素 按绝对值k加和 执行算法 但我发现这是行不通的。取集合(-5,10),看看是否有子集加起来等于5。我们将转换(-5,10)->(0,15)和5->10-5+10=5,但0+15!=十, 我在网上搜索了很多想法,但找不到答案 #include <stdio.
k
k
添加集合中的每个元素k
加和但我发现这是行不通的。取集合(-5,10),看看是否有子集加起来等于5。我们将转换(-5,10)->(0,15)和5->10-5+10=5,但0+15!=十,
我在网上搜索了很多想法,但找不到答案
#include <stdio.h>
typedef int bool;
#define true 1
#define false 0
bool isSubsetSum(int set[], int n, int sum) {
// Base Cases
if (sum == 0)
return true;
if (n == 0 && sum != 0)
return false;
if (set[n - 1] > sum)
return isSubsetSum(set, n - 1, sum);
return isSubsetSum(set, n - 1, sum) ||
isSubsetSum(set, n - 1, sum - set[n - 1]);
}
int main() {
int set[] = { -3, 34, -2, 12, 5, 8 };
int sum = 0;
int i;
int n = sizeof(set) / sizeof(set[0]);
if (isSubsetSum(set, n, sum) == true)
printf("Found a subset");
else
printf("No subset");
return 0;
}
#包括
typedef int bool;
#定义真1
#定义false 0
bool isSubsetSum(整数集[],整数n,整数和){
//基本情况
如果(总和=0)
返回true;
如果(n==0&&sum!=0)
返回false;
如果(设置[n-1]>总和)
返回isSubsetSum(集合,n-1,sum);
返回isSubsetSum(集合,n-1,总和)||
isSubsetSum(集合,n-1,和集合[n-1]);
}
int main(){
int set[]={-3,34,-2,12,5,8};
整数和=0;
int i;
int n=sizeof(set)/sizeof(set[0]);
if(isSubsetSum(设置,n,和)=真)
printf(“找到子集”);
其他的
printf(“无子集”);
返回0;
}
我想您可以通过删除溢出测试来尝试暴力尝试:
#include <stdio.h>
int isSubsetSum(int set[], int n, int sum, int empty_ok) {
// Base Cases
if (sum == 0 && empty_ok)
return 1;
if (n == 0)
return 0;
return isSubsetSum(set, n - 1, sum, empty_ok) ||
isSubsetSum(set, n - 1, sum - set[n - 1], 1);
}
int main(void) {
int set[] = { 3, 34, 2, 12, 5, 8 };
int n = sizeof(set) / sizeof(set[0]);
int sum = 6;
if (isSubsetSum(set, n, sum, 0) == true)
printf("Found a subset");
else
printf("No subset");
return 0;
}
#包括
int isSubsetSum(int set[],int n,int sum,int empty_ok){
//基本情况
如果(总和=0&&empty\u确定)
返回1;
如果(n==0)
返回0;
返回isSubsetSum(设置,n-1,求和,空\u确定)||
isSubsetSum(集合,n-1,和集合[n-1],1);
}
内部主(空){
int set[]={3,34,2,12,5,8};
int n=sizeof(set)/sizeof(set[0]);
整数和=6;
if(isSubsetSum(设置,n,求和,0)=真)
printf(“找到子集”);
其他的
printf(“无子集”);
返回0;
}
不幸的是,这个解决方案的时间复杂度是O(2n)
以下是针对最多64个元素的设置的非递归解决方案:
int isSubsetSum(int set[], int n, int sum) {
unsigned long long last;
if (n == 0)
return sum == 0;
last = ((1ULL << (n - 1)) << 1) - 1;
// only find non empty subsets for a 0 sum
for (unsigned long long bits = 1;; bits++) {
int s = 0;
for (int i = 0; i < n; i++) {
s += set[i] * ((bits >> i) & 1);
}
if (s == sum)
return 1;
if (bits == last)
return 0;
}
}
int isSubsetSum(int set[],int n,int sum){
未签名的长最后;
如果(n==0)
返回和==0;
最后=((1全部i)和1);
}
如果(s==总和)
返回1;
如果(位==最后一位)
返回0;
}
}
说明:类型
无符号long
保证至少有64个值位<代码>位从1
到最后一个
不等,并将n
位的所有可能位模式都取下,但全部关闭除外。对于位的每个值
,我对设置了相应位的元素求和,因此测试所有可能的非空子集。我真的不理解您的策略。您不应该使用绝对值。a+b
的和与|a |+b |
的和几乎没有关系(好吧,有一些关系,但是如果你在某处使用它们,那么我就错过了;)
如果您有一种算法,可以在正整数中找到一个子集,这些正整数加起来等于x
,那么您也可以将其用于负数。它不会那么有效,但只要有一个小技巧,它就可以工作
首先,向所有数字添加一个偏移量,使它们都为正。现在,您将查找总计为x+y*offset
的子集,其中y
是子集的大小。你有
A = -1, -3, -2, 6 12, 48
您正在寻找一个子集,其总和为0
,然后首先将3添加到所有数字中
b = 2, 0, 1, 9, 15, 51
然后试着找到一个子集大小1
加起来就是3
,一个子集大小2
加起来就是6
,一个子集大小4
,加起来就是12
,这就是
12 = 2+0+1+9 ie 0 = -1 + -3 + -2 + 6
这样做不是很有效,因为您必须应用算法N
-次(N
=输入大小)。但是,如果您的正数算法允许您修正子集的大小,这可能会补偿效率上的损失。代码有TBD错误
但OP要求它留下来。我以后再修或者明天取下来
OP的代码有问题,因为它正在搜索错误的
和
通过找到最小值并对集合[]
的每个元素进行偏移,问题变成了唯一的正数之一——显然OP之前已经解决了这个问题
诀窍是目标sum
需要用n*offset
#include <stdio.h>
#include <stdbool.h>
//typedef int bool;
//#define true 1
//#define false 0
bool isSubsetSum(int set[], int n, int sum, int offset) {
// Base Cases
if ((sum + n*offset) == 0)
return true;
if (n == 0 && (sum + n*offset) != 0)
return false;
if (set[n - 1] > sum + n*offset)
return isSubsetSum(set, n - 1, sum, offset);
return isSubsetSum(set, n - 1, sum, offset) ||
isSubsetSum(set, n - 1, sum - set[n - 1], offset);
}
int main() {
int set[] = { -3, 34, -2, 12, 5, 8 };
int sum = 0;
int i;
int n = sizeof(set) / sizeof(set[0]);
int min = -3; // TBD code to find minimum
for (i = 0; i<6; i++) set[i] -= min;
if (isSubsetSum(set, n, sum, -min) == true)
printf("Found a subset");
else
printf("No subset");
return 0;
}
typedef int bool#定义真1定义假0 <代码>好上帝,不,选一种语言,请高兴。这不是C++!但我发现这是行不通的。这不是一个有用的问题描述。你到底是指C和C++中的负值子集和?TBH,我真的不明白你想做什么,但是,如果你有一个适用于正整数的alogrithm,你可以简单地添加一个偏移量,使所有数字都为正,然后通过查找大小为1的子集加起来等于x+偏移量,大小为2的子集加起来等于x+偏移量*2,等等,来应用该算法。。。,其中x是你要找的实际和,我知道,但也许这可以通过递归得到?尽管如此,还是要感谢这个例子。我的主要问题是,必须使用sum=0。但是,始终显示如果sum=0,则会找到十个子集。@AdomasArabella:这是一个最多64个元素的非递归解决方案。子集可以为空。我的程序的目的是寻找空和。我的意思是,集合{1,-3,-2,612,48}我必须找到一个子集和,它是0-1+-3+-2+6=0。类型无符号长
保证至少有64个值位<代码>位
从1
到last
不等,包含所有n
位的可能位模式。对于
Found a subset