问题:(1) 有一个集合R = [a, b, c, d, e, f, g, h, i, j, k, l, m, n, ],
(2) 由一组R的真子集构成的集合Rn = [R1, R2, R3, R4, R5],其中
R1 = [ a, c, e, g, i, k, l, m]
R2 = [ b, c, d, h, k]
R3 = [ d, f, g, n]
R4 = [ b, f, g, i, j]
R5 = [ b, k, n]
(3) 给定一个目标集 C = [b, d, f, l, n], C为R的子集
[问题]求在Rn中找出个数最少的一个子集,这个子集的所有元素的并集为U,要求U ∩ C = C,且U ∪ C = U,请写出求解这样的一个子集的通用算法。
matlab实现code
%%
%author: qkk
%date: 20190917
%%
R = 'abcdefghijklmn'; % full Set
S = {'acegiklm', 'bcdhk', 'dfgn', 'bfgij', 'bkn'}; % set composed of subset of R
T = 'bdfln'; % target set
% convert data to binary Matrix and binary Vector
CR = zeros(1,length(R)) + 1;
numR = size(S,2);
CS = zeros(numR,length(R));
for i=1:numR
SItem = S{i};
for j=1:length(SItem)
CS(i,strfind(R, SItem(j))) = 1;
end
end
CT = zeros(1, length(R));
for i=1:length(T)
CT(strfind(R,T(i))) = 1;
end
% call function
rIndex = SetDist(CR,CS,CT);
% output
disp('required subset:')
rIndex = sort(rIndex);
for i=1:length(rIndex)
disp(S{rIndex(i)});
end
%%
% input demo:
% U = [1 1 1 1 1 1 1 1 1 1 1 1 1 1];
% S = [1 0 1 0 1 0 1 0 1 0 1 1 1 0;
% 0 1 1 1 0 0 0 1 0 0 1 0 0 0;
% 0 0 0 1 0 1 1 0 0 0 0 0 0 1;
% 0 1 0 0 0 1 1 0 1 1 0 0 0 0;
% 0 1 0 0 0 0 0 0 0 0 1 0 0 1];
% T = [0 1 0 1 0 1 0 0 0 0 0 1 0 1];
function index = SetDist(U, S, T)
% INPUT:
% -U: Full set,all elements equal 1, size: [1,|R|]
% -S: Multiple subset of U,each row represent a subset of U,value 1 denote
% the Subset contains the corresponding element, 0 otherwise, size:[|Rn|, |R|]
% -T: Target set,within value denote same means with S
% OUTPUT:
% -index: Index of required subset
if nargin ~= 3
disp('Warning: Improper number of input parameter');
return;
end
index = [];
[numR, numElm] = size(S);
% check input
if length(U) ~= size(S,2) || length(U) ~= length(T) ...
|| ~isempty(find(U ~= 1))
disp('Warning: Improper input');
return;
end
rowCount = zeros(numR,1); %each element denotes the length of intersetion between each row(R) of S and T
colCount = zeros(1,numElm); % each element denotes the number of subset that contains the element in T
%query if solution exist
bitQ = sum(S)-T;
if length(find(bitQ <0)) > 0
disp('Warning: no solution!');
return;
end
% solve: cycle until each element in T is contained by a subset
while sum(T) ~= 0
satIndex = find(T == 1);
colCount = sum(S(:,satIndex));
for i=1:numR
rowCount(i) = sum(S(i,:) & T);
end
sortColCount = sort(colCount);
firstValIndex = find(colCount == sortColCount(1));
if (sortColCount(1) == 1)
adjustCols = satIndex(firstValIndex);
for i=1:length(adjustCols)
whichOne = find(S(:,adjustCols(i)) == 1);
index = [index whichOne];
% update S and T
adjustColsOfi = find(S(whichOne,:) == 1);
%S(:,adjustColsOfi) = 0;
T(adjustColsOfi) = 0;
end
else
maxRowCount = max(rowCount);
mRCIndex = find(rowCount == maxRowCount);
index = [index mRCIndex(1)];
% update T
resetIndex = find(S(mRCIndex(1),:)==1);
T(resetIndex) = 0;
%for i=1:length(resetIndex)
% S(:,resetIndex(i)) = 0;
%end
end
end
end