Gunther was already on the right track. Do you want to select an item if
- string cumsum non-zeros 1 AND
- column cumsum non-zeros 1 AND
- the element itself is not equal to zero.
The following code solves the problem:
A = [0, 0, 3, 4; 4, 3, 2, 0; 2, 0, 2, 0]; batches = cell(0); while any(A(:)~=0) selector = cumsum(A~=0, 1) .* cumsum(A~=0, 2) .* (A~=0) == 1; batches{end+1} = A .* selector; A(selector) = 0; end
Please note that the returned solution is not optimal, as its second batch
0 0 0 4 0 3 0 0 2 0 0 0
which means that the remaining elements of the matrix belong to one column:
0 0 0 0 0 0 2 0 0 0 2 0
Unfortunately, you cannot draw them in one batch. Thus, you get four batches instead of three.
Edit: Perhaps it is a good idea to first select those items that appear in rows / columns with lots of non-zero items. For example, you can use these weights.
weight = repmat(sum(A~=0, 1), size(A, 1), 1) ... .* repmat(sum(A~=0, 2), 1, size(A, 2)) .* (A~=0) weight = 0 0 6 2 6 3 9 0 4 0 6 0
Next algorithm
batches = cell(0); while any(A(:)~=0) batch = zeros(size(A)); weight = repmat(sum(A~=0, 1), size(A, 1), 1) ... .* repmat(sum(A~=0, 2), 1, size(A, 2)) .* (A~=0); while any(weight(:)~=0) [r,c] = find(weight == max(weight(:)), 1); batch(r,c) = A(r,c); A(r,c) = 0; weight(r,:) = 0; weight(:,c) = 0; end batches{end+1} = batch; end
returns these parties.
batches{:} ans = 0 0 0 4 0 0 2 0 2 0 0 0 ans = 0 0 3 0 4 0 0 0 0 0 0 0 ans = 0 0 0 0 0 3 0 0 0 0 2 0
So he worked, at least for this little test case.