6
public int maximumANDSum(int[] nums, int numSlots) {7
this.memo = new int[1 << (2 * numSlots)];9
this.numSlots = numSlots;13
int helper(int numIndex, int set) {14
// Base case when we used all the numbers15
if (numIndex == nums.length) return 0;16
// Set informs BOTH the slots used and the numIndex. If the later17
// statement surprises you, think it like this: We must place all18
// the numbers in a slot, so how many slots are used in numIndex=10?19
// yes! 9 slots (because we will use the 10th now!), so the set will20
// have 10 ones. No other numIndex will have 9 ones. So having memo21
// with 2 dimentions would be redundant, as you would naver have a22
// combination of numIndex 3 with sets 1, 2, 4, 6.. etc, only23
// numIndex 2 will have those sets.24
if (memo[set] > 0) return memo[set] - 1; // I use memo-1 so I dont have to fill it with -126
for (int i = 0; i < numSlots; i++) {27
int firstHalfSlot = (set & (1 << i)) == 0 ? i : -1; // -1 if it is used29
(set & (1 << (i + numSlots))) == 0 ? i + numSlots : -1; // -1 if it is used30
int slotChosen = firstHalfSlot > -1 ? firstHalfSlot : secondHalfSlot;31
if (slotChosen < 0) continue; // both slots are used33
if (slotChosen >= numSlots) andSum = ((slotChosen - numSlots) + 1) & nums[numIndex];34
else andSum = (slotChosen + 1) & nums[numIndex];35
// By adjusting the set in the recursion signature36
// I am backtracking in an elegant way.37
max = Math.max(max, andSum + helper(numIndex + 1, set | 1 << slotChosen));39
memo[set] = max + 1; // I use memo+1 so I dont have to fill it with -1