具有相同长度的2行的C ++算法

时间:2016-07-18 13:06:38

标签: c++ algorithm

我找不到解决这个问题的好方法: 我们有5< = k< = 50段,长度为1到1000个单位。 计划必须从这些细分中构建两个具有相同长度的支柱。 程序必须找到最大可能的支柱长度。

例如: 5段长度:1 5 2 3 4 正确的解决方案是:第一支柱2 + 5 = 7,第二支柱3 + 4 = 7。

你会如何处理?

2 个答案:

答案 0 :(得分:1)

维基百科有一篇关于the Partition Problem in Computer Science的文章,其主管听起来就像你想要做的那样。

  

在计算机科学中,分区问题(或数字分区1)   是决定给定的多重S是否为正的任务   整数可以分成两个子集S1和S2,使得   S1中的数字之和等于S2中数字的总和。虽然   分区问题是NP完全的,有一个伪多项式   时间动态编程解决方案,并有解决方案的启发式   在许多情况下,无论是最佳还是近似的问题。对于   这个原因,它被称为"最简单的NP难问题"。

提供了几种不同的算法来提供解决方案。

另见以下内容。

Is partitioning an array into halves with equal sums P or NP?

3-PARTITION problem

custom partition problem

C++ Elegant solution to partition problem

答案 1 :(得分:0)

这是一些奇怪的代码,但这是它的工作。 (注意,没有对此代码应用优化,可能运行缓慢, 最适合小集 - x!复杂度)

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...

另请注意,我重载了运算符&lt;&lt;对于各种容器,此输出仅适用于我的其他文件。这是每个人的版本 (只是打印部分):

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;
}