提供数字列表以确定哪个组合为您提供给定值

时间:2012-04-19 20:51:25

标签: c++

好的,所以我的编程技巧真的是新手和超级生锈,但这是我的问题。我需要一种方法来获取给定数字的列表并将它们组合在一起以确定哪个组合等于某个数量。我的妻子在百事可乐工作,他们必须亲手做到这一点,她让我帮助她。如果可能的话,我将用c ++尝试这个。谢谢你们。

P.S。这是我得到的信息,如果它有帮助。 http://dl.dropbox.com/u/9609070/Photo/Pepsi.tiff

1 个答案:

答案 0 :(得分:1)

我继续前进,做了一个粗暴的事情。如果你让它运行很长一段时间,它会完成工作,但绝对比人们快得多。我使用了一个整数列表来使测试更容易,因此每个int都应该有一个double。

#include <algorithm>
using std::accumulate;
using std::distance;
using std::includes;
using std::next_permutation;
using std::sort;

#include <fstream>
using std::ifstream;

#include <iostream>
using std::cout;

#include <vector>
using std::vector;

int main()
{
    const int wantedSum = 100; //this is your wanted sum here

    vector<int> v; //stores all of the numbers to choose from
    vector<vector<int>> matches; //stores combinations (no different ordering)

    ifstream inFile ("combination sum.txt"); //file to read values from

    int input;
    while (inFile >> input) //fill v with values
        v.push_back (input);

    inFile.close();

    for (vector<int>::size_type subSize = 1; subSize < v.size(); ++subSize) //go from 1 element at a time to the number to choose from
    {
        vector<int> sub (subSize); 
        sort (v.begin(), v.end()); //sort original vector

        do
        {
            for (vector<int>::iterator it = sub.begin(); it != sub.end(); ++it) //fill subvector with first n values in v
                *it = v.at (distance (sub.begin(), it));

            if (accumulate (sub.begin(), sub.end(), 0) == wantedSum) //check for sum
            {
                sort (sub.begin(), sub.end()); //sort subvector

                bool found = false; //check if same (but different order) as another
                for (const auto &element : matches)
                    if (includes (element.begin(), element.end(), sub.begin(), sub.end()))
                    {
                        found = true;
                        break;
                    }

                if (!found) //if it isn't the same as any
                {
                    matches.push_back (sub); //push sorted vector

                    cout << '{'; //output match

                    for (const auto &element : sub)
                        cout << element << ' ';

                    cout << "\b}\n";
                }
            }
        } while (next_permutation (v.begin(), v.end())); //go onto next permutation of v (this is what causes uber slowness as v's size grows)
    }
}

输入:

45
24
3
79
8
30
55
27
34
9

输出:

{45 55}
{3 8 34 55}
{9 27 30 34}
{3 9 24 30 34}

执行时间(你的可能会更高):0.840s

我不是说这是最好的解决方案,但它确实有效。当然,与我给出的列表相比,你的列表相当大,所以它需要更长的批次

哦,其中一些将需要C ++ 11进行编译。它可能只是ranged-for循环和双直角括号。它们可以用

修复
for_each (vec.begin(), vec.end(), some_func); //in algorithm

vector<vector<int> > v;

分别。如果能在合理的时间内完成工作,请干杯。

编辑:

for (const auto &element : sub)...替换为

for (vector<int>::const_iterator it = sub.begin(); it != sub.end(); ++it)
    if (includes (element.begin(), element.end(), sub.begin(), sub.end()))
    {
        found = true;
        break;
    }

如果不是因为你需要访问std::for_each里面的内容,它可以用found替换,所以它会回到显式循环。