C++ C++;两条等长直线的算法

C++ C++;两条等长直线的算法,c++,algorithm,C++,Algorithm,我找不到解决这样一个问题的好办法: 我们有5篇维基百科上有一篇文章,关于这篇文章的线索听起来像是你想要做的 在计算机科学中,分区问题(或数字分区) 确定给定多集是否为正的任务 整数可以分成两个子集S1和S2,这样 S1中的数字之和等于S2中的数字之和。虽然 划分问题是NP完全问题,存在一个伪多项式 时间动态规划的解决方案,并有启发式解决 该问题在许多情况下都是最优或近似的。对于 因此,它被称为“最简单的NP难问题” 有几种不同算法的参考,以提供解决方案 另见下文 这是一些奇怪的代码,但它确

我找不到解决这样一个问题的好办法:
我们有5篇维基百科上有一篇文章,关于这篇文章的线索听起来像是你想要做的

在计算机科学中,分区问题(或数字分区) 确定给定多集是否为正的任务 整数可以分成两个子集S1和S2,这样 S1中的数字之和等于S2中的数字之和。虽然 划分问题是NP完全问题,存在一个伪多项式 时间动态规划的解决方案,并有启发式解决 该问题在许多情况下都是最优或近似的。对于 因此,它被称为“最简单的NP难问题”

有几种不同算法的参考,以提供解决方案

另见下文


这是一些奇怪的代码,但它确实起作用了。 (注意,此代码未应用任何优化,可能运行缓慢, 最适用于小型集合-
x!
complexity)

模板
内联设置所有_子集(常量Cont和Cont)
{
设置所有_子集;
续空;
所有_子集。向后推_(空);
对于(自动it1=cont.begin();it1!=cont.end();++it1)
{
设置临时_子集=所有_子集;
用于(自动和it2:临时子集)
it2.push_back({*it1,std::distance(cont.begin(),it1)});
用于(常数自动和it2:温度子集)
所有_子集。向后推_(it2);
}
返回所有_子集;
}
模板
内联布尔值与秒相交(常数连续&第一,常数连续&第二)
{
对于(自动it1:第一个)
用于(自动it2:秒)
如果(it1==it2)
返回true;
返回false;
}
模板
内联控制第一次生成向量(常数控制)
{
控制结果;
用于(const auto&it:cont)
结果:将_向后推(首先推);
返回结果;
}
模板
内联控制生成向量秒数(常数控制)
{
控制结果;
用于(const auto&it:cont)
结果。推回(第二次);
返回结果;
}
模板
内联行李完整和分区(常数控制和控制)
{
自动子集=所有_子集(续);
包结果;
用于(自动it1:子集)
用于(自动it2:子集)
{
auto it1_firsts=将_firsts(it1)的向量_生成;
auto it2_firsts=将_firsts(it2)的向量_生成;
if(std::累加(it1_firsts.begin(),it1_firsts.end(),0)
==
std::累加(it2_firsts.begin(),it2_firsts.end(),0))
{
if(以秒为单位与μ相交(it1,it2)
||
it1.size()!=it2.size())
继续;
结果:推回(成对)
(it1_第一,
it2(美国第一),;
}
}
返回结果;
}
int main()
{
std::向量向量向量{1,4,9,16,25,36,49,64};
自动结果=完整和分区(vec);
用于(常量自动和x:结果)

std::cout看起来像一个竞赛问题这不是提问的正确方式。但是提示:对于每一个数字,分别获得它与所有其他数字的总和。你将得到一个矩阵。在整个矩阵中找到最大值。检查你是否在其他地方找到了最大值,如果没有,则取整个矩阵的第二个最大值并重新检查,直到找到为止“匹配”老实说,这听起来像是子集和问题的重复应用。可能是NP-完全问题。在123456789的例子中,你可以省去1,用23889和4567达到22。这很容易找到,因为数字是连续的。听起来像你想要做的。维基百科文章有一些算法。还有一些补充子集和的nal答案。阶乘复杂性?这比2^n更糟糕。如果输入50,OP可能会看到,宇宙将在计算完成之前结束。@AndyG True,但我没有必要的理论知识来实现任何更快的版本。我知道比x^{2,3,4…}更复杂的一切都非常糟糕(如以下代码:))这是公平的。不过,作为参考,一个蛮力解决方案,它计算所有可能的组合,然后迭代,直到找到两个相同且最大的组合,它只能是O(2^N)这还不到N!。我并没有真正解析你的代码,所以我不知道你的真正复杂性是否是这样。我建议你研究一下Karps 21 NP完全问题,如果你想了解更多,也许可以深入研究一下如何通过简化来证明一个问题是NP完全的。
template<template<typename...> class Set = std::vector,
         template<typename...> class Pair = std::pair,
         template<typename...> class Cont,
         typename... Ts>
inline Set<Cont<Pair<typename Cont<Ts...>::value_type, size_t>>> all_subsets(const Cont<Ts...>& cont)
{
    Set<Cont<Pair<typename Cont<Ts...>::value_type, size_t>>> all_subsets;
    Cont<Pair<typename Cont<Ts...>::value_type, size_t>> empty;
    all_subsets.push_back(empty);

    for(auto it1 = cont.begin(); it1 != cont.end(); ++it1)
    {
        Set<Cont<Pair<typename Cont<Ts...>::value_type, size_t>>> temp_subset = all_subsets;
        for(auto& it2 : temp_subset)
            it2.push_back({*it1, std::distance(cont.begin(), it1)});
        for(const auto& it2 : temp_subset)
            all_subsets.push_back(it2);
    }
    return all_subsets;
}

template<template<typename...> class Cont,
         typename... Ts>
inline bool intersects_by_second(const Cont<Ts...>& first,  const Cont<Ts...>& second)
{
    for(auto it1 : first)
        for(auto it2 : second)
            if(it1 == it2)
                return true;
    return false;
}

template<template<typename...> class Cont,
         typename... Ts>
inline Cont<typename Cont<Ts...>::value_type::first_type> make_vector_of_firsts(const Cont<Ts...> cont)
{
    Cont<typename Cont<Ts...>::value_type::first_type> result;
    for(const auto& it : cont)
        result.push_back(it.first);
    return result;
}

template<template<typename...> class Cont,
         typename... Ts>
inline Cont<typename Cont<Ts...>::value_type::second_type> make_vector_of_seconds(const Cont<Ts...> cont)
{
    Cont<typename Cont<Ts...>::value_type::second_type> result;
    for(const auto& it : cont)
        result.push_back(it.second);
    return result;
}

template<template<typename...> class Bag = std::vector,
         template<typename...> class Pair = std::pair,
         template<typename...> class Cont,
         typename... Ts>
inline Bag<Pair<Cont<Ts...>, Cont<Ts...>>> full_sum_partition(const Cont<Ts...>& cont)
{
    auto subsets = all_subsets(cont);

    Bag<Pair<Cont<Ts...>, Cont<Ts...>>> result;

    for(auto it1 : subsets)
        for(auto it2 : subsets)
        {
            auto it1_firsts = make_vector_of_firsts(it1);
            auto it2_firsts = make_vector_of_firsts(it2);
            if(std::accumulate(it1_firsts.begin(), it1_firsts.end(), 0)
               ==
               std::accumulate(it2_firsts.begin(), it2_firsts.end(), 0))
            {
                if(intersects_by_second(it1, it2)
                   ||
                   it1.size() != it2.size())
                    continue;
                result.push_back(Pair<Cont<Ts...>, Cont<Ts...>>
                                 (it1_firsts,
                                  it2_firsts));
            }
        }
    return result;
}



int main()
{
    std::vector<int> vec{1,4,9,16,25,36,49,64};
    auto result = full_sum_partition(vec);

    for(const auto& x : result)
        std::cout << x << " with sum " << std::accumulate(x.first.begin(),
                                                          x.first.end(),
                                                          0) << std::endl;
}
([], []) with sum 0
([1, 25, 36], [4, 9, 49]) with sum 62
([16, 25, 36], [4, 9, 64]) with sum 77
([4, 9, 49], [1, 25, 36]) with sum 62
([16, 49], [1, 64]) with sum 65
([4, 36, 49], [9, 16, 64]) with sum 89
([1, 16, 36, 49], [4, 9, 25, 64]) with sum 102
([1, 64], [16, 49]) with sum 65
([4, 9, 64], [16, 25, 36]) with sum 77
([9, 16, 64], [4, 36, 49]) with sum 89
([4, 9, 25, 64], [1, 16, 36, 49]) with sum 102
Press <RETURN> to close this window...
for(const auto& x : result)
{
    size_t i=0;
    std::cout << "([";
    for(i=0; i< x.first.size(); ++i)
        std::cout << x.first[i] << "],"[(i<x.first.size()-1)];
    if(i==0)
        std::cout << ']';
    std::cout << ",[";
    for(i=0; i< x.second.size(); ++i)
        std::cout << x.second[i] << "],"[(i<x.first.size()-1)];
    if(i==0)
        std::cout << ']';
    std::cout << ')'
              << " with sum " << std::accumulate(x.first.begin(),
                                                x.first.end(),
                                                0) << std::endl;
}