计算从N个列表中选择数字的方法

时间:2014-08-03 04:50:03

标签: c++ algorithm

给定N个列表,其数字可以在1到100之间。

我想要多种方法来选择数字,每个不同的列表中的一个不允许重复。

注意:如果选择的任何数字不同,则两种方式不同。

示例:

List 1 : 5, 100, 1
List 2 : 2
List 3 : 5, 100
List 4 : 2, 5, 100

因为我想从每个中选择一个数字而不重复。

在这种情况下的答案是:2(1,2,5,100和1,2,100,5)。

我的方法:我尝试使用包含和排除原则解决它。但是如何找到所有交叉点?

我在想,可以通过匹配同时获取1组中的列表和相应的映射数字来解决它吗?

N最多可以为10,每个列表的数字可以在1-100之间。

此外,每个列表中只有一个数字。

1 个答案:

答案 0 :(得分:0)

这是所提出的@robertking算法的实现

注意:

  • 使用std::vector<bool>存储已使用的数字(针对STL的大多数实现中的bool作为位进行了优化)。
  • 使用cache变量(动态编程)加速以前获得的结果进行大搜索。
  • 使用TRACE define打印解决方案。

代码(在Windows中使用C ++ 11在GCC 4.9.0中测试):

#include <iostream>
#include <bitset>
#include <vector>
#include <map>

#define TRACE

typedef std::vector<bool> used_numbers_t;
typedef std::vector<int> list_t;
typedef std::vector<list_t> lists_t;

typedef std::map<std::pair<used_numbers_t, unsigned int>, int> cache_t;
cache_t cache;

long solve(used_numbers_t& used_numbers, const lists_t& lists, list_t& generated_solution, unsigned int list_idx = 0, int solutions = 0) {
    if (list_idx == lists.size()) {
#ifdef TRACE
        for (auto gs : generated_solution) {
            std::cout << gs << ",";
        }
        std::cout << std::endl;
#endif
        return solutions + 1;
    }

    auto key = std::make_pair(used_numbers, list_idx);
    auto it = cache.find(key);
    if (it != cache.cend()) {
        return it->second;
    }

    long actual_solutions = 0;
    auto& processing_list = lists[list_idx];
    for (unsigned int idx = 0; idx < processing_list.size(); idx++) {
        if (!used_numbers[processing_list[idx] - 1]) {
            used_numbers[processing_list[idx] - 1] = true;
#ifdef TRACE
            generated_solution.push_back(processing_list[idx]);
#endif

            actual_solutions += solve(used_numbers, lists, generated_solution, list_idx + 1, solutions);

#ifdef TRACE
            generated_solution.pop_back();
#endif
            used_numbers[processing_list[idx] - 1] = false;
        }
    }

    cache.insert(std::make_pair(key, actual_solutions));

    return solutions + actual_solutions;
}

int main(int argc, char* argv[]) {
    lists_t lists{{5, 100, 1}, {2}, {5, 100}, {2, 5, 100}};

    used_numbers_t used_numbers(100);
    list_t generated_solution;
    long solutions = solve(used_numbers, lists, generated_solution);
    std::cout << "The total number of solutions is: " << solutions << std::endl;

    return 0;
}

获得输出:

1,2,5,100,
1,2,100,5,
The total number of solutions is: 2