Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何找到所有匹配的数字,其总和为';N';在给定数组中_C++_Algorithm_Stl Algorithm - Fatal编程技术网

C++ 如何找到所有匹配的数字,其总和为';N';在给定数组中

C++ 如何找到所有匹配的数字,其总和为';N';在给定数组中,c++,algorithm,stl-algorithm,C++,Algorithm,Stl Algorithm,我的目标是找到所有可能的组合,它们的总和等于给定的总和。 例如,如果数组是 25934359862104如果总数为12,则可能的组合为 2 10 3 9 8 4 5 3 4 这是我编写的第一组代码。想知道在这方面可以做哪些最好的改进 int find_numbers_matching_sum(int *number_coll, int total) { int *search_till = lower_bound(number_coll,number_coll+TOTAL_SI

我的目标是找到所有可能的组合,它们的总和等于给定的总和。 例如,如果数组是 25934359862104如果总数为12,则可能的组合为

2 10
3 9
8 4
5 3 4
这是我编写的第一组代码。想知道在这方面可以做哪些最好的改进

   int find_numbers_matching_sum(int *number_coll, int total)
{

    int *search_till = lower_bound(number_coll,number_coll+TOTAL_SIZE, total);
    int location = search_till - number_coll;
    if (*search_till > total && location > 0 )
    {
        --location;
    }

    while ( location >= 0 )
    {
        find_totals(number_coll,total,location);
        --location;
    }
    return 1;
}

int find_totals(int *number_coll, int total, int end_location)
{
    int left_ones = total - number_coll[end_location];
    int curloc = end_location;
    int *search_till = 0;
    int location ;
    int all_numbers[10];
    int i = 0;

    all_numbers[i] = number_coll[end_location];
    while ( left_ones && curloc >= 0 )
    {
        search_till = lower_bound(number_coll,number_coll+end_location, left_ones);
        location = search_till - number_coll;
        if (*search_till > left_ones && location > 0 )
        {
            --location;
        }
        else if ( left_ones < *search_till )
        {
            break;
        }
        curloc=location;
        left_ones = left_ones - number_coll[curloc];
        all_numbers[++i] = number_coll[curloc];
        end_location = curloc - 1;
    }

    if ( !left_ones )
    {
        while ( i>=0)
        {
            cout << all_numbers[i--] << ' ';
        }
    }
    cout << endl;
    return 1;


}
int find\u numbers\u matching\u sum(int*number\u coll,int total)
{
int*search\u till=下限(number\u coll,number\u coll+总大小,总计);
int location=search\u till-number\u coll;
如果(*搜索到>总数和位置>0)
{
--位置;
}
而(位置>=0)
{
查找总数(编号、总数、位置);
--位置;
}
返回1;
}
int find_totals(int*number_coll,int total,int end_location)
{
int left_ones=总数[end_location];
int curloc=结束位置;
int*search_till=0;
int定位;
整型所有_数[10];
int i=0;
所有编号[i]=编号[end\U location];
while(左&&curloc>=0)
{
搜索直到=下限(数字集合,数字集合+结束位置,左集合);
位置=搜索时间-编号\u coll;
如果(*搜索到>左侧(&&location>0)
{
--位置;
}
else if(左<*搜索到)
{
打破
}
curloc=位置;
left_one=left_one-number_coll[curloc];
所有数字[++i]=数字[curloc];
结束位置=CULLOC-1;
}
如果(!左_个)
{
而(i>=0)
{

cout这是,的一个变体。通过连续降低N,完整的背包问题可以线性地简化为您的问题。如果p!=NP保持不变,您将找不到一个精确的算法来解决您的问题,该算法在N中的运行速度比指数更快


多项式时间近似是已知的。

您描述的问题也被称为which is。您所能达到的最佳效果是指数时间算法,它尝试数组/集合的所有可能子集。

这是子集和问题(),直到p?=NP,只有指数解


如果值不大,比如说你的总和以M为界,你可以使用。假设有N个项目

假设你有一个矩阵
DP[M][N]
。单元格
DP[M][N]
的意思是:前N个元素的多少个组合正好和M相加

分析每个项目时,您可以将其包含在某些组合中,也可以不将其包含在某些组合中。然后,您将获得重复周期(考虑超出范围的值)

rhs的第一项表示您正在考虑所有不使用第N项的和,第二项表示所有使用第N项的和。您从基础
DP[0][0]=1开始,因为空集是一个有效的组合,其和为0。所需的值以DP[M][N]为单位

虽然这是伪多项式,
O(MN)
这与数论有关,可以用动态规划来解决

n
为总数。设
parts
为元素列表。我们假设它们是正整数

if parts == []
then f(n,parts) = [] 
else let parts = x::queue and f(n,parts) = union(L1, L2)

where:

L1 = f(n, queue)

if n-x>0
then let result = f(n-x, queue) and L2 = concatenation([x], result)
else if n-x==0, L2 = [x]
else L2 = []
这是一份家庭作业。

#包括
#包括
使用名称空间std;
结构状态{
INTV;
恒定状态*rest;
无效转储()常量{
如果(休息){

不能使用
lower_bound()
您似乎假设集合是有序的?允许负数吗?在这个解决方案中,我在调用函数之前对数字进行排序。但是有更好的方法吗?实际上,只要这些数字都是正数,就像nsivakr的例子中一样,问题就出在P中(我想).对于正数,你知道什么时候你超过了目标。@Pontus我不得不反对。典型的背包问题是用非负数来描述的。@Pontus即使这个数是正数,这个问题也是NP完全问题。如果我理解你的话,这个问题要求精确的和。@Peter:真的吗?KP要求你同时最大化e一个大小范围内的独立值函数:这是我们这里没有的自由度。正子集和问题有两个参数:n和c,其中n是项数,c是期望和。我得到了至少一个以n和c为多项式边界的算法(尽管是paywalled):……但我也得到了关于NP的其他主张().现在我完全糊涂了!你能用正子集和问题来表达可判定性问题吗?+1 OP的实际问题可能会满足额外的约束。如果他试图列出可能性,这并没有真正的帮助。这只会计算它们。此外,你可以用一个向量来表示,你不需要矩阵。@|Vlad:你说得对。因为输出可能是指数大小,所以没有希望了。我知道可以用向量来完成,但用矩阵来解释算法似乎更容易。@Neil:拜托,我们的笑话线程中已经有足够的xkcd了,这只是偷取了屏幕属性,可以让其他答案在不滚动的情况下可见。@nsivakr,也许有e如果您对数字的位表示有所了解,则可以进行进一步优化。例如,如果目标是奇数,且集合中只有一个奇数,则您知道必须包含该奇数。然后,搜索可以在容易证明解决方案不可能的地方进行修剪。如果您预期在解决方案是修改“ss(ip+1,end,target,state);”,这样它不仅跳过第一个元素,而且跳过与第一个元素相同的所有元素。
if parts == []
then f(n,parts) = [] 
else let parts = x::queue and f(n,parts) = union(L1, L2)

where:

L1 = f(n, queue)

if n-x>0
then let result = f(n-x, queue) and L2 = concatenation([x], result)
else if n-x==0, L2 = [x]
else L2 = []
#include <iostream>
#include <vector>

using namespace std;

struct State {
    int v;
    const State *rest;
    void dump() const {
        if(rest) {
            cout << ' ' << v;
            rest->dump();
        } else {
            cout << endl;
        }
    }
    State() : v(0), rest(0) {}
    State(int _v, const State &_rest) : v(_v), rest(&_rest) {}
};

void ss(int *ip, int *end, int target, const State &state) {
    if(target < 0) return; // assuming we don't allow any negatives
    if(ip==end && target==0) {
        state.dump();
        return;
    }
    if(ip==end)
        return;
    { // without the first one
        ss(ip+1, end, target, state);
    }
    { // with the first one
        int first = *ip;
        ss(ip+1, end, target-first, State(first, state));
    }
}

int main() {
    int a[] = { 2,59,3,43,5,9,8,62,10,4 };
    int * start = &a[0];
    int * end = start + sizeof(a) / sizeof(a[0]);
    ss(start, end, 12, State());
}