是否存在一种智能算法,该算法采用多种概率并在多维数组或容器内生成相应的真值表
前:
n = 3
N : [0 0 0
0 0 1
0 1 0
...
1 1 1]
我可以使用for循环和Ifs,但我知道我的方式将是缓慢和耗时的。所以,我问如果有一个高级功能,我可以尽可能高效地使用它?
答案 0 :(得分:8)
如果我们允许用全零填充表来启动,那么应该可以执行完全2^n - 1
次填充以设置我们想要的1位。这可能不会比写一个手动循环更快,但它完全没有信息。
编辑:
第std::vector<std::vector<int> > output(n, std::vector<int>(1 << n));
行声明了向量的向量。外部向量是长度n,内部向量是2^n
(n个输入的真值结果的数量)但是我通过使用左移来进行功率计算,因此编译器可以插入常量而不是调用,说,pow
。在n=3
我们最终使用3x8向量的情况下。我以这种方式组织它(而不是以行作为第一个索引的惯用8x3),因为我们将在输出数据中利用基于列的模式。以这种方式使用vector
构造函数还可以确保向量向量的每个元素都初始化为0.因此,我们只需要担心将我们想要的值设置为1并将其余部分保留下来。
第二组嵌套for
循环仅用于在结束时打印出结果数据,没有什么特别的。
第一组for循环实现了真正的算法。我们在这里利用输出数据中的基于列的模式。对于给定的真值表,最左边的列将有两个部分:前半部分全部为0而后半部分全部为1.由于我们预先填充了零,因此将从中间开始的一半填充一半的列高度将适用我们需要的所有1个。第二列将具有行1/4 0,1 / 4,1 / 4,0,1 / 1.因此,两个填充将应用我们需要的所有1。我们重复这一步,直到我们到达最右边的列,在这种情况下,每隔一行是0或1。
我们开始说“我需要一次填充一半的行”(unsigned num_to_fill = 1U << (n - 1);
)。然后我们遍历每一列。第一列从要填充的位置开始,并用1填充那么多行。然后我们增加行并将填充大小减半(现在我们一次填充1/4行,但我们跳过空白下一列的行和第二次填充。
例如:
#include <iostream>
#include <vector>
int main()
{
const unsigned n = 3;
std::vector<std::vector<int> > output(n, std::vector<int>(1 << n));
unsigned num_to_fill = 1U << (n - 1);
for(unsigned col = 0; col < n; ++col, num_to_fill >>= 1U)
{
for(unsigned row = num_to_fill; row < (1U << n); row += (num_to_fill * 2))
{
std::fill_n(&output[col][row], num_to_fill, 1);
}
}
// These loops just print out the results, nothing more.
for(unsigned x = 0; x < (1 << n); ++x)
{
for(unsigned y = 0; y < n; ++y)
{
std::cout << output[y][x] << " ";
}
std::cout << std::endl;
}
return 0;
}
答案 1 :(得分:1)
您可以通过注意矩阵中的每一行代表一个n位二进制数来将他的问题分成两部分,其中n是概率数[sic]。
所以你需要:
编辑:
如果你只是担心运行时,那么对于常数n,你总是可以预先计算表,但它认为你在计算它时会遇到O(2 ^ n)复杂度
答案 2 :(得分:0)
您希望在二进制数字系统中写入0到2 ^ N - 1的数字。没有什么聪明的。您只需填充二维数组的每个单元格。你不能比这更快。
你可以直接在数字上迭代。请注意,最右边的列重复0 1
,然后下一列重复0 0 1 1
,然后是下一列0 0 0 0 1 1 1 1
,依此类推。每列重复2 ^ columnIndex(从0开始)零,然后是1。
答案 3 :(得分:0)
详细说明jk的回答...... 如果你有n个布尔值(“概率”?),那么你需要
答案 4 :(得分:0)
卡诺图或Quine-McCluskey
http://en.wikipedia.org/wiki/Karnaugh_map http://en.wikipedia.org/wiki/Quine%E2%80%93McCluskey_algorithm
这应该让你朝着正确的方向前进,以尽量减少最终的真值表。