假设我在A中有7个项目,在B中有4个项目
A=[10;40;90;130;200;260;320]
B=[100;300;500;1000]
我希望列出可能的组合,其中:
任何人都知道如何在Matlab中做到这一点?
我的尝试:
X=sum(A);
y=1;
for Y=1:((length(A))-1);
X=X+B(y);
if(X>2000)
disp('Following is unacceptable')
end
y=y+1
end
但是这段代码不正确。它只是添加B的第一个元素,然后添加第二个元素,依此类推。它没有为我提供可能的组合。
示例:
如果将来A或B的值发生变化,我希望自动化。我不确定这是否也是概率的情况。
答案 0 :(得分:4)
只需使用nchoosek
和双for
- 循环即可浏览B
中所有可能的元素组合:
SA = sum(A);
for k = 1:numel(B)
for idx = nchoosek(1:numel(B), k)'
B_subset = B(idx);
if (SA + sum(B_subset) <= 2000)
disp([A(:)', B_subset(:)'])
end
end
end
这将打印所有小于(或等于)2000的组合。对于您的示例,我们得到:
10 40 90 130 200 260 320 100
10 40 90 130 200 260 320 300
10 40 90 130 200 260 320 500
10 40 90 130 200 260 320 100 300
10 40 90 130 200 260 320 100 500
10 40 90 130 200 260 320 300 500
10 40 90 130 200 260 320 100 300 500
内部for
- 循环:
内部for
- 循环使用nchoosek(1:numel(B), k)
,它生成1 ...长度(B)中的所有k长度组合(我正在使用numel
而不是length
出于习惯;在这种情况下,它具有相同的效果)。例如,在我们的案例中,B
有4个元素,因此对于k = 3
,我们得到nchoosek(1:4, 3)
:
1 2 3
1 2 4
1 3 4
2 3 4
我们得到的是B
中元素索引的所有可能的k长度组合。在每次迭代中,此for
- 循环为idx
指定不同的索引组合。我们如何将B
的索引转换为真实元素?我们只写B(idx)
在内部循环中测试组合:如果总sum(A) + sum(B(idx))
小于(或等于)2000,则显示该组合。
外部for
- 循环:
外部for
- 循环简单地遍历所有可能的组合长度(即,k
的所有可能值)。
希望有所帮助!
未来的一些MATLAB编程技巧:
1.变量名称区分大小写
2.您不需要增加循环变量。 for
循环会自动为您执行此操作。
答案 1 :(得分:2)
假设B不是很长(大约10个元素),通过所有组合进行详尽搜索都可以正常工作。您可以使用递归函数执行此详尽搜索,但下面的代码使用了一种在MATLAB中特别简洁的技巧:它通过将每个组合表示为二进制位字符串来扫描B的所有元素组合。
% examine each of 2^length(B) combinations
for i=0:2^length(B)-1
% converts the binary string into an array of 0 and 1 used to select elements in B
combo = dec2bin(i, length(B))-'0';
% print the combination of elements if their sum is large
if combo * B + sum(A) > 2000
disp(find(combo));
end
end
有2 ^长度(B)可能的组合。这将依次检查它们,将组合表示为长度长度(B)的二进制字符串,并评估这些元素的总和(带有位串和B之间的点积)。
答案 2 :(得分:2)
最好的方法是涉及一些递归,如下所示:
sumA=sum(A);
find_CombinationsOfB(B,sumA,[])
function ret=findCombinationsOfB(in_vals,total_sum,already_contained)
if total_sum>2000
ret=false;
else
for y=1:length(in_vals);
if (~findCombinationsOfB(in_vals([1:(y-1);(y+1):length(in_vals)],total_sum+in_vals(y),[already_contained in_vals(y))
display([already_contained in_vals])
end
end
ret=true;
end
基本上它的作用是尝试B的每个组合。它将打印任何不加起来的2000,包括来自A的总和。
一步一步,这是它的作用:
如果您想了解更多有关其工作方式的信息,请在函数开头打印in_vals,total_sum和already_contained,如下所示:
fprintf("in_vals=%s total_sum=%i already_contained=%s",mat2str(in_vals),total_sum,mat2str(already_contained));
它应该在每次迭代时向您显示正在发生的事情。