我很难弄清楚如何有效地解决这个问题。让我描述一下它是如何进行的:
“一位勤劳的妈妈为她的 3 个孩子 Amelia、Jessica 和 Bruno 买了几种营养价值不同的水果。两个女孩都超重,而且她们非常恶毒,总是让可怜的布鲁诺一无所有,所以他们的母亲决定分享食物以下方式:
- 阿米莉亚是最重的人获得最多的营养价值
- 杰西卡得到的金额等于或少于阿米莉亚
- 布鲁诺得到的数量等于或少于杰西卡,但你需要找到一种方法,在尊重规则的同时给他尽可能高的营养价值(A >= J >= B)”
注意:原问题描述不同,但思路是一样的,我不希望我的同学在google寻求帮助时找到这个帖子嘿嘿。
我老师给的一个测试用例如下:
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
注意:我知道在孩子们中间有几种挖水果的方法,但只要遵循规则 A >= J >= B,这并不重要。
起初我做了一个算法来生成所有子集,每个子集都有它们的总和,以及正在使用的位置。该方法很快被丢弃,因为水果列表最多可以有 50 个水果,并且子集算法是 O(2^n)。我内存不足。
我的第二个想法是使用动态编程。在列标题中,我将有水果列表的位置,在行标题中相同,用字母很难解释,所以我将提前为前面的例子做表格 { 4, 2, 1, 8 , 11, 5, 1}。
00 01 02 03 04 05 06 07
00
01
02
03
04
05
06
07
每次我们前进到下面的行时,我们都会添加位置 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)
现在您知道它是如何进行的,让我们添加第一行
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
我放了 00,因为第一个位置已经在使用中。完成的表格将如下所示。
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
现在我们有了桌子。我将营养价值的总和除以孩子的数量,32/3 = 10.6667,上限为 11。我尝试检查 11,如果它在表中,我选择它并标记行的位置和使用的表的列,然后我会尝试再次检查 11,如果它在表中,我会选择它,否则查看 10 或 9 等,直到找到它。之后,我会将相应的位置标记为已使用,然后将未使用的位置相加以获得布鲁诺的果实。
我知道必须有更好的方法来做到这一点,因为我发现我的方法存在缺陷,该表只有几个子集的总和。所以也许这在一些测试用例中是有害的。也许是一个 3D Memoization Cube?,我认为它会消耗太多内存,而且我也有 256MB 的限制。
哇,我没有意识到我输入了这么多 xX 我希望我不会得到很多 tl;博士。任何帮助/指南将不胜感激:D
编辑:我编写了生成表格的代码,以防有人想尝试。
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();
}
}