我本质上是想弄清楚如何为M个对象的不同配置的基础向量生成代码到N个不同的状态(例如,如果我在2个孩子之间有2个小吃,我可以有(2,0)(0) ,2)或(1,1),可怕的例子,但那就是这个想法)
我正在努力弄清楚如何在不进入许多不同循环的情况下做到这一点(我希望这是自动的)。我们的想法是创建一个矩阵,其中每一行都是长度为M的向量。我将以vec(1)= N开始,然后是if循环,其中如果sum(vec)== N,Matrix(1,:)= vec ;然后我可以采取vec(1)= N-i并做同样的事情。
我唯一的问题是我没有看到如何使用if并忘记它,所以如果我在5个位置可能有2个对象,我将如何获得(1 0 0 0 1)。
我没有看到如何做到这一点。
答案 0 :(得分:1)
您可以使用递归函数:
function out = combos(M,N)
if N == 1
out = M;
else
out = [];
for i = 0:M
subout = combos(M-i,N-1);
subout(:,end+1) = i;
out = [out;subout];
end
end
答案 1 :(得分:1)
我认为这可以做你想要的。
关键的想法是不要生成每个组中的元素数量,而是生成组之间的分割点。这可以通过重复组合来完成。 Matlab的nchoosek
生成组合而不重复,但这些组合很容易转换成我们需要的。
M = 5; % number of objects
N = 3; % number of groups
t = nchoosek(1:M+N-1, N-1); % combinations without repetition...
t = bsxfun(@minus, t, 1:N-1); % ...convert into combinations with repetition
t = diff([zeros(size(t,1), 1) t repmat(M, size(t,1), 1) ], [], 2); % the size of each
% group is the distance between split points
在此示例中,结果为
t =
0 0 5
0 1 4
0 2 3
0 3 2
0 4 1
0 5 0
1 0 4
1 1 3
1 2 2
1 3 1
1 4 0
2 0 3
2 1 2
2 2 1
2 3 0
3 0 2
3 1 1
3 2 0
4 0 1
4 1 0
5 0 0
答案 2 :(得分:1)
这是Luis'没有bsxfun
的类似方法。因为我们不喜欢有趣。
n = 5;
k = 3;
c = nchoosek(n+k-1, k-1);
result = diff([zeros(c, 1) nchoosek(1:(n+k-1), k-1) ones(c, 1)*(n+k)], [], 2) - 1;
这将创建长度为n
的整数k
的分区。给定一个长度为n + (k-1)
的数组,我们找到(k-1)
个位置的所有组合,以在(一元)整数之间放置分区。对于5个项目和3个位置,我们有7个选择放置分区的位置:
[ 0 0 0 0 0 0 0 ]
如果我们选择的组合为[2 4]
,我们会将位置2
和4
替换为分区,如下所示:
[ 0 | 0 | 0 0 0 ]
O
给出一元的值,因此这个组合是1 1 3
。为了轻松恢复这些值,我们只需在数组左侧和右侧的下一个值(0
和n+k
)增加虚拟分区的组合,然后取差并减去1
(因为分区本身对值没有贡献):
diff([0 2 4 8]) - 1
ans =
1 1 3
通过将分区滑入每个可能的位置组合,我们得到n
的所有分区。
输出:
result =
0 0 5
0 1 4
0 2 3
0 3 2
0 4 1
0 5 0
1 0 4
1 1 3
1 2 2
1 3 1
1 4 0
2 0 3
2 1 2
2 2 1
2 3 0
3 0 2
3 1 1
3 2 0
4 0 1
4 1 0
5 0 0