I'm having a very hard time trying to figure out how to solve this problem efficiently. Let me describe how it goes:
"A hard working mom bought several fruits with different nutritional values for her 3 kids, Amelia, Jessica and Bruno. Both girls are overweight, and they are very vicious and always leave poor Bruno with nothing, so their mother decided to share the food in the following manner:
Note: The original problem is described differently but the idea is the same, I don't want my classmates to find this post when they google for help hehe.
One of the test cases given by my teacher is the following:
The fruit list has the following values { 4, 2, 1, 8, 11, 5, 1}
Input:
7 -----> Number of Fruits
4 2 1 8 11 5 1 ----> Fruits Nutritional Values
Output:
1 11 ----> One fruit, their nutritional values sum for Amelia
5 ----> Position of the fruit in the list
3 11 ----> Three fruits, their nutritional values sum for Jessica
1 2 6 ----> Position of the fruits in the list
3 10 ----> Three fruits, their nutritional values sum for Bruno
3 4 7 ----> Position of the fruits in the list
Note: I am aware that there are several ways of diving the fruits among the kids, but it doesn't really matter as long as it follows the rule A >= J >= B.
At first I made an algorithm that generated all the subsets, each one had their sums, and the positions that were in use. That method was quickly discarded because the list of fruits can have up to 50 fruits, and the subset algorithm is O(2^n). I ran out of memory.
The second idea that I have is to use Dynamic Programming. In the columns header I would have the positions of the Fruit's List, in the row header the same, it's kind of hard to explain with letters so I'll ahead an do the table for the previous example { 4, 2, 1, 8, 11, 5, 1}.
00 01 02 03 04 05 06 07
00
01
02
03
04
05
06
07
Each time we advance to the row below we add the positions 1,2,3,...,7
00 01 02 03 04 05 06 07
00 00 <---No positions in use
01 04 <---RowPosition 1 + Column Position(Column 0) (4+0)
02 06 <---RowPosition 1 + RowPosition 2 + Column Position (4+2+0)
03 07 <---RP(1) + RP(2) + RP(3) + CP(0) (4+2+1+0)
04 15 <--- (4+2+1+8+0)
05 26
06 31
07 32 <--- (4+2+1+8+11+5+1+0)
Now that you know how it goes lets add the first row
00 01 02 03 04 05 06 07
00 00 04 02 01 08 11 05 01 <-- Sum of RP + CP
01 04 00 06 05 12 15 09 05 <-- Sum of RP(0..1) + CP
02 06
03 07
04 15
05 26
06 31
07 32
I put the 00 because the 1st position is already in use. The completed table would look like this.
00 01 02 03 04 05 06 07
00 00 04 02 01 08 11 05 01
01 04 00 06 05 12 15 09 05
02 06 00 00 07 14 17 11 07
03 07 00 00 00 15 18 12 08
04 15 00 00 00 00 26 20 16
05 26 00 00 00 00 00 31 27
06 31 00 00 00 00 00 00 32
07 32 00 00 00 00 00 00 00
Now that we have the table. I divide the sum of the Nutritional Values by the amount of kids, 32/3 = 10.6667, the ceiling would be 11. I try to check for 11, if it's in the table, I choose it and mark the position of the row and columns of the tables as used, then I would try to check for 11 again, if it's in the table I choose it otherwise look the 10, or 9, etc until I find it. Afterwards I would mark the respective positions as used then sum the unused positions to get Bruno's fruits.
I know that there has to be better way to do this because I found a flaw in my method, the table only has the sum of a few subsets. So maybe that will be detrimental in a few test cases. Maybe a 3D Memoization Cube?, I think it would consume too much memory, and I have a limit too 256MB.
Wow, I didn't realize I typed this much x.X. I hope I don't get a lot of tl; dr. Any help / guide would be greatly appreciated :D
EDIT: I made the code that generates the table in case anyone wants to try it out.
static void TableGen(int[] Fruits)
{
int n = Fruits.Length + 1;
int[,] memo = new int[n, n];
for (int i = 1; i < n; i++)
{
memo[0, i] = Fruits[i - 1];
memo[i, 0] = memo[i - 1, 0] + Fruits[i - 1];
for (int j = i + 1; j < n; j++)
memo[i, j] = memo[i, 0] + Fruits[j - 1];
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
Console.Write("{0:00} ", memo[i, j]);
Console.WriteLine();
}
}
A slightly computationally intensive way would be to assign the fruit in a round robin way, starting with the highest nutritional value for amelia.
From there, progressively loop through the fruit from lowest nutritional value held by amelia, and try each combination of either (a) giving the fruit to jessica, or (b) swapping the fruit with one held by jessica, while still satisfying the rule.
Then apply the same method to jessica and bruno. Repeat these 2 loops until no more swaps or gives are possible.
Slightly trickier, but potentially faster, would be to simultaneously give/swap to jess/bruno. For each 2 pieces of fruit that A holds, you would have 4 options to try, with more if you at the same time try and balance J & B.
For a faster algorithm, you could try asking at the mathematics stack exchange site, as this is very much a set-theory problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With