【问题标题】:Finding all possible permutations with a sum constraint and a redundancy option? (MATLAB)使用总和约束和冗余选项查找所有可能的排列? (MATLAB)
【发布时间】:2015-09-13 16:41:33
【问题描述】:

我想到了以下问题:

假设有一位受人尊敬的音乐家退休了。音乐家不时收到他们过去录音的版税支票。音乐家的版税支票总是以:

1 美元、5 美元、8 美元、12 美元、17 美元、20 美元、42 美元、100 美元或 200 美元

这意味着音乐家只收到上面指定金额的版税支票。我想知道,我将如何计算音乐家可以获得 1,000 美元的报酬的可能方式总数?在这个问题中有一些限制/允许的假设。它们是:

(1) 音乐家获得 1,000 美元的“支票”总额没有上限。例如,音乐家可以收到 1,000 张 1 美元支票、5 张 200 美元支票,或 10 张 20 美元支票和 4 张 200 美元支票等。

(2) 正如 (1) 所暗示的,您可以收到任何支票的倍数(事实上,所有单一支票选项的总和总计 405 美元,因此这个条件必须积累 1,000 美元)。

(3) 顺序很重要。获得报酬 200 美元、200 美元、100 美元、100 美元、100 美元、100 美元、100 美元和 100 美元与 100 美元、100 美元、100 美元、100 美元、100 美元、100 美元、200 美元和 200 美元是不同的“解决方案”,这也是不同的“解决方案”超过 200 美元、100 美元、100 美元、200 美元、100 美元、100 美元、100 美元和 100 美元,即使这两种解决方案都包含 6 张 100 美元支票和 2 张 200 美元支票。请记住,音乐家“不时地”获得有偿支票,因此支票接收的顺序使得不同解决方案(排列)的可能性成为可能。

我感兴趣的是只找到解决这个问题的解决方案的总数,而不是打印出来。

这是我目前的方法:

  • 定义表示检查可能性的变量(例如 x1 = 1、x2=5、x3 = 8 等)

  • 加入一些 if-then 语句,检查一组 x1、x2、x3...xn 的倍数是否等于 1000

  • 如果是,则将某个计数器变量加 1

  • 一旦所有迭代都用完/所有循环边界都完成,显示计数器值。

但是,我不知道如何将 x1、x2、x3 及其排列合并到给定的方程中,也不知道如何求解这样的方程。

【问题讨论】:

  • 总是有一张 1 美元的支票吗?所有其他检查都是最小检查的整数倍吗?
  • 不,并不总是有 1 美元的支票。一直有一张 1 美元的支票会减少很多“目标金额”整数倍的可能性,比如 5 张 200 美元的钞票或 125 张 8 美元的钞票。

标签: algorithm matlab constraints permutation


【解决方案1】:

这是我解决它的想法,遵循动态规划的模式:

checks=[1,5,8,12,17,20,42,100,200];
target=300;
M=[checks;ones(size(checks))];
while M(1,1)<target
    %we know that there are #possibilities to get a sum of value
    value=M(1,1);
    possibilities=M(2,1);
    M(:,1)=[];
    disp(value)
    %combine value with each check:
    for idx=1:numel(checks)
        if value+checks(idx)<=target
            ii=find(M(1,:)==value+checks(idx),1,'first');
            if isempty(ii)
                M(:,end+1)=[value+checks(idx),possibilities];
            else
                M(2,ii)=M(2,ii)+possibilities;
            end
        end
    end
    %Sort M by value
    [a,idx]=sort(M(1,:));
    M=M(:,idx);
end

您可以手动完成,创建一个表(变量 M),其中包含值(汇总)和获得该值的可能性数量。对于您可以通过检查直接获得的每个值,将其初始化为 1 种可能性。

现在重复,直到你得到你想要的值:

  • 从表中弹出您的第一个条目(最小值)。将其与每张支票重新组合(使用一次)并将其重新插入表中。
  • 当组合值已经在表中时,将数字相加。
  • 当组合值不在表中时,插入新条目。

虽然在理论上这种方法是精确的,但它很快超过了浮点精度。对于目标值 300,结果为 ~10^42,超过了浮点精度。符号工具箱是否可用,那么您可以切换到 vpa 吗?

【讨论】:

  • 10^42 似乎有点高。如果我取每个面额的最大计数{$1:0-300, $5:0-60, $8:0-37, ... $200:0-1},并取他们的乘积,它只会达到大约10^11。对于1000 的目标,我得到~10^16。这肯定在 64 位类型的范围内,并不是该计数中的所有组合都有效。
  • @beker:顺序很重要,这进一步增加了可能性。
  • 我完全错过了。这应该可以解释一些事情。
  • 非常感谢,很容易理解。
  • 有上限排列的数学表示吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多