I can't think of any algorithm that computes directly what you want without searching the solution space.
However, you want better performance than your complex recursive algorithm.
I think that can be had by using a non-recursive approach.
Data structures you already have:
- a Map, MatchesToMembers, taking us from Match # to Set of Member #s
Let's add to that a complementary structure for reverse lookup:
- a Map, MembersToMatches, taking us from Member # to Match #'s, initially empty
And a data structure of possible match grouping candidates, which will be
- a Map, Candidates, taking us from Candidate # to Boolean,
- initially all true
- sized of 2^(# Matches)
Let's populate this new data structure (#2):
for each Match# as Key in MatchesToMembers for each Member# in MatchesToMembers[Match#] Update MembersToMatches[Member#] to include Match# next next
We now have (#2) MembersToMatches as follows:
A1: S1, S3 A3: S2, S3 B2: S1, S2 B4: S3 B5: S3
Let's populate the Candidate data structure (#3) from the other (#2):
for each MatchSet as Value in MembersToMatches if MatchSet has more than one member then Assemble a Candidate mask from the set of Match#'s by accumlating (1<<Match#) for each Match# in the MatchSet Reject all Candidates at that mask
And (#3) Candidates as follows
0 true (the empty candidate) 1 true (candidate having match#1 only) 2 true (candidate having match#2 only) 3 false (candidate having match1&2) 4 true (candidate having match#3 only) 5 false (candidate having match#1&3) 6 false (candidate having match#2&3) 7 false (candidate having all matches)
Hopefully you can see that we're using a bit values of the solution space for the Key in the Candiates map. E.g. Candidate #5 (it's index/Key) in binary is 101, meaning consider the solution of taking Set 3 and Set 1 (in your 1-based set #'ering).
Now we compute the score for each non-rejected candidate, and take the max.
Rejection from candidate mask as all the elements in the set are known to they interfere with each other:
for each index as Key in Candidate if index & CandidateIndexMask == CandidateIndexMask then Candidate[index] = false endif next
Max computation
for index as Key in Candidate if Candidate[index] then compute score for Candidate if larger than before, then keep it endif next
if your Candidate#'s are small (e.g. less than 32), then you can do this with a simple for (int index = 0; index < count; index++) { }
, however, for a larger set you'd need a bit vector for the index variable (and the ability to "increment" a bit vector).
Also, these algorithms & data structures can be used with bit vectors instead of individual elements or sets or other. if we work on bit vectors we can work on chunks of 64-bits at at time reducing the iterations by a large factor.