Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 算法-如何从数组中的每列中选择一个数字,使其总和尽可能接近某个特定值_Arrays_Algorithm_Select_Sum_Permutation - Fatal编程技术网

Arrays 算法-如何从数组中的每列中选择一个数字,使其总和尽可能接近某个特定值

Arrays 算法-如何从数组中的每列中选择一个数字,使其总和尽可能接近某个特定值,arrays,algorithm,select,sum,permutation,Arrays,Algorithm,Select,Sum,Permutation,我有一个m x n实数矩阵。我希望从每一列中选择一个值,以便所选值的总和尽可能接近预先指定的总和 我不是一个有经验的程序员(尽管我有一个有经验的朋友会帮忙)。我想用Matlab、Mathematica或C++实现这一点(如果需要的话,MySQL)。 代码只需要运行几次,每隔几天运行一次-它不一定需要优化。我将有16列和大约12行。在不知道可能填充数组的值的范围的情况下,像这样的通用值如何: 将目标除以剩余列数 从最接近该值的列中选择数字 从1开始重复。直到每列都被选中 通常我会建议使用动态规划,

我有一个m x n实数矩阵。我希望从每一列中选择一个值,以便所选值的总和尽可能接近预先指定的总和

我不是一个有经验的程序员(尽管我有一个有经验的朋友会帮忙)。我想用Matlab、Mathematica或C++实现这一点(如果需要的话,MySQL)。
代码只需要运行几次,每隔几天运行一次-它不一定需要优化。我将有16列和大约12行。

在不知道可能填充数组的值的范围的情况下,像这样的通用值如何:

  • 将目标除以剩余列数
  • 从最接近该值的列中选择数字
  • 从1开始重复。直到每列都被选中

  • 通常我会建议使用动态规划,但这种情况有一些特点,建议使用另一种方法。首先,性能要求较低;这个程序将只运行几次,而且它听起来好像运行时间在几个小时左右不会有问题。其次,矩阵相当小。第三,矩阵包含实数,因此有必要进行取整,然后进行某种复杂的搜索,以确保不会错过最佳可能性

    相反,我将建议以下半暴力方法
    12**16~1.8e17
    ,可能的选择总数太多了,但是
    12**9~5.2e9
    可以用蛮力来完成,而且
    12**7~3.6e7
    可以轻松地放在内存中。计算前七列的所有可能选项。按总数对这些可能性进行排序。对于最后九列的每个可能选择,使用有效的搜索算法在前七列中找到最佳匹配。(如果你有很多记忆,你可以试试8和8。)

    我尝试C++中的第一个实现,使用<代码> STD::排序和 STD::LoWiLoWix > <代码> <代码>标准标题。测量它;如果太慢,那么试试内存中的B+树(Boost有吗?)


    我花了更多的时间思考如何以最简单的方式实现上面写的内容。这里有一种方法可以很好地用于64位机器上的12 x 16矩阵,该机器的内存大约为4GB

    前八列的选择数为
    12**8
    。每个选项由一个介于
    0
    12**8-1
    之间的4字节整数表示。要解码选择索引
    i
    ,第一列的行由
    i%12
    给出。更新
    i/=12。现在第二列的行由
    i%12
    等给出

    一个包含所有选项的向量大约需要
    12**8*4
    字节,或大约1.6GB。两个这样的向量需要3.2 GB。为前八列准备一个,为后八列准备一个。按它们所指示的条目之和对它们进行排序。使用鞍形搜索查找最佳组合。(将迭代器初始化为第一个向量,将反向迭代器初始化为第二个向量。当两个迭代器都不在其末尾时,将当前组合与当前最佳值进行比较,并在必要时更新当前最佳值。如果当前组合和大于目标值,则递增第一个迭代器。如果和大于目标值,则递增(使用第二个迭代器。)


    我估计这需要少于50行的C++。< /P>值的范围是多少?特别是,数字可以是负数吗?如果这是一个家庭作业,你可能会在课程材料中找到关于算法的提示。听起来像是一个优化问题。@ooga实数不是正数吗?我已经有一段时间没有学数学了,所以我可能错了。由于速度很大程度上取决于蛮力部分,如果你将缓存的总和存储在磁盘上,你可能仍然很好。(特别是当算法使用相同的值重复运行时)。磁盘查找可能听起来很慢,但您知道所需的近似值。不需要BTrees,只需按所需值对文件进行排序。如果您还对其他列进行排序(按列中的值排序,然后按最小-最大差值降序排序),您将重复使用来自文件相同近似部分的值。第二种方法肯定更好。但是4GB的内存并不是真正必要的。我们可以将所有需要的数据保存在CPU缓存中。诀窍是(不是对8列的每一个和进行排序)只需按排序顺序生成这些和:对前4列的每一个和进行排序;删除重复项;这是数组

    A
    ;用同样的方法从接下来的4列中准备数组
    B
    ;将
    A[0]
    添加到
    B
    的每个元素中,并将结果推送到优先级队列中;移除PQ的顶部元件后,将其替换为相同的
    B
    元件加上
    A
    的下一个元件;在PQ不为空时重复此操作。