【发布时间】:2012-07-02 01:02:09
【问题描述】:
我很难弄清楚如何有效地解决这个问题。让我描述一下它是怎么回事:
“一位勤劳的妈妈为她的三个孩子Amelia、Jessica和Bruno买了几种营养价值不同的水果。两个女孩都超重,而且她们非常恶毒,总是让可怜的Bruno一无所有,所以他们的妈妈决定分享食物按以下方式:
- 阿米莉亚体重最重,营养价值最高
- Jessica 得到的金额等于或小于 Amelia
- Bruno 得到的食物量等于或少于 Jessica,但您需要找到一种方法,在遵守规则 (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。
哇,我没有意识到我输入了这么多 x.X。我希望我不会得到很多 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();
}
}
【问题讨论】:
-
示例输出不满足指定规则。
-
“Amelia 是最重的人得到最多的水果”这意味着你需要给她最多的营养价值或 FruitCount?
-
您是否还有其他规则被省略?否则,只需给 Amelia 最高 NV 项目,Jessica 次之,Bruno 次之。重复直到你没有食物。这将为您提供 A >= J >= B,但不会使它们的总值尽可能接近。
-
我修正了我说“阿米莉亚是最重的人得到最多的水果”的规则,而它应该是营养价值。
-
这个问题本身就是疯了。这个前提是人为的,没有通过现实世界的气味测试。案例中的母亲应该让两个超重的女孩严格节食,并让专业人士对她们的情绪/心理障碍进行检查。布鲁诺应该被送去和他的祖父母住在一起。如果你的老师想出了这个问题,请让他/她想出更好的故事,因为这个很烂。