你试过了什么?
考虑到你所说的问题(它指定我们必须使用递归),这个想法很简单:对于你可以采取的每个项目,看看是否最好采取它。所以只有两种可能的路径:
- 你拿了项目
- 你不要接受它
当您拿走该项目时,将其从列表中删除,并将容量减小该项目的重量。
如果不获取项目,请从列表中删除 if,但不会减少容量。
有时,它有助于打印递归调用的外观。在本例中,它可能如下所示:
Calling 11 8 7 6 5 with cap: 20
+Calling 8 7 6 5 with cap: 20
| Calling 7 6 5 with cap: 20
| Calling 6 5 with cap: 20
| Calling 5 with cap: 20
| Result: 5
| Calling 5 with cap: 14
| Result: 5
| Result: 11
| Calling 6 5 with cap: 13
| Calling 5 with cap: 13
| Result: 5
| Calling 5 with cap: 7
| Result: 5
| Result: 11
| Result: 18
| Calling 7 6 5 with cap: 12
| Calling 6 5 with cap: 12
| Calling 5 with cap: 12
| Result: 5
| Calling 5 with cap: 6
| Result: 5
| Result: 11
| Calling 6 5 with cap: 5
| Calling 5 with cap: 5
| Result: 5
| Result: 5
| Result: 12
+Result: 20
Calling 8 7 6 5 with cap: 9
Calling 7 6 5 with cap: 9
Calling 6 5 with cap: 9
Calling 5 with cap: 9
Result: 5
Calling 5 with cap: 3
Result: 0
Result: 6
Calling 6 5 with cap: 2
Calling 5 with cap: 2
Result: 0
Result: 0
Result: 7
Calling 7 6 5 with cap: 1
Calling 6 5 with cap: 1
Calling 5 with cap: 1
Result: 0
Result: 0
Result: 0
Result: 8
Result: 20
我确实故意向容量为20的[8 7 6 5]显示呼叫,结果为20(8 + 7 + 5)。
请注意,[8 7 6 5] 被调用两次:一次的容量为 20(因为我们没有采用 11),一次的容量为 9(因为容量为 11)。
因此,解决方案的路径:
11 未取,呼叫 [8 7 6 5],容量为 20
8 人,致电 [7 6 5],容量为 12 人(20 - 8 人)
7 人,呼叫 [6 5],容量为 5 (12 - 7)
6 个未被占用,呼叫 [5],容量为 5
5个被拿走了,我们处于零。
Java中的实际方法可以容纳很少的代码行。
由于这显然是家庭作业,我只用骨架来帮你:
private int ukp( final int[] ar, final int cap ) {
if ( ar.length == 1 ) {
return ar[0] <= cap ? ar[0] : 0;
} else {
final int[] nar = new int[ar.length-1];
System.arraycopy(ar, 1, nar, 0, nar.length);
fint int item = ar[0];
if ( item < cap ) {
final int left = ... // fill me: we're not taking the item
final int took = ... // fill me: we're taking the item
return Math.max(took,left);
} else {
return ... // fill me: we're not taking the item
}
}
}
我确实将数组复制到一个新数组中,这效率较低(但无论如何,如果您寻求性能,递归不是这里要走的路),但更“实用”。