从N个列表中选择数字的计数方法
Counting ways to select numbers from N lists
给定N个从1到100的列表
我想要选择数字的方法的数量,从每个不同的列表中选择一个,而不允许重复。
注意:如果选择的数字不同,则两种方式不同。
示例:
List 1 : 5, 100, 1
List 2 : 2
List 3 : 5, 100
List 4 : 2, 5, 100
因为我想从每个数字中选择1个数字,而不重复。
在这种情况下答案将是:2(1,2,5,100和1,2,100,5)。
我的方法:我尝试用包容和排斥的原则来解决它。但是如何找到所有的交叉点呢?
我在想,在一个集合中取列表,在另一个集合中取对应的映射数,可以用匹配来解决吗?
N最大可达10,每个列表的数字可以在1-100之间。
这是@robertking算法的一个实现
指出:
- 使用
std::vector<bool>
存储已经使用的数字(在大多数STL实现中都优化了将bool存储为位)。 使用 - 使用
TRACE
定义打印或不打印溶液
cache
变量(动态规划)加速先前获得结果的大搜索。代码(在GCC 4.9.0和Windows下的c++ 11中测试):
#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
相关文章:
- 实现基于数字值(正、负、零)的条件表达式的最佳方法
- 将一系列数字映射到 CPP 中的值的简单方法
- 找到所有与自己求和的数字X的快速方法,去掉一个数字得到N
- 有没有更简单的方法可以从用户那里获取三个数字并按升序打印它们?
- 有效创建数字签名的正确方法是什么?我可以使用DSA_sign_setup()吗?
- 有什么方法可以在 c++ 中组织"cycling"(循环)数字?
- 查看数字是否包含在未排序的双数字间隔内的最有效方法?
- isdigit() 和 isalnum() 给出错误,因为输入是一个常量字符并且无法转换。其他可能查看输入是否为数字的方法?
- 有没有一种更快的方法,从特定的数字池中获取随机数
- sort() 方法 c++ 中的比较器函数.为大量数字获得不同的解决方案
- 在向量中找到连续数字的更有效方法
- 获取数字小数部分的最佳方法
- 获取数字最左边两个位的值的最便宜的方法是什么?
- 将两位数字转换为低内存表示的最快方法
- C/C++ 方法中最快/最短计算二进制数字总和/又名二进制中的 1 数
- 总结数字字符串输入的最佳方法
- 搜索字符串是否至少包含一次从 0 到 9 的所有数字的最有效方法
- 在C++有没有更好的方法可以做到这一点?检查哪些数字满足条件 [A*B*C = A! + B! + C!]
- C++:有哪些常规方法可以使代码更有效地用于大数字
- 对这些 n^2 个数字进行排序的最快方法是什么