简体   繁体   English

这个背包问题的解决方案有什么问题?

[英]What is wrong in this knapsack problem solution?

I understand that this is more of a problem solving than a coding question as such, so my apologies if this post breaks any rules here, but does anyone have any idea how best to go about this?我知道这更多的是解决问题而不是编码问题,所以如果这篇文章违反了这里的任何规则,我深表歉意,但是有人知道如何最好地向 go 发送这方面的信息吗?

I am trying to solve the problem, but there is a logical error in my code, or rather I have not considered all the conditions, tell me how to find it.我正在尝试解决问题,但我的代码中存在逻辑错误,或者说我没有考虑所有条件,请告诉我如何找到它。

The problem: An adventurer found himself in a dungeon full of treasures.问题:一位冒险家发现自己身处充满宝藏的地牢中。 However, before entering he activated a trap, which in t minutes will flood the entire room.然而,在进入之前,他启动了一个陷阱,在 t 分钟内,这个陷阱将淹没整个房间。 You are given an array of chests, where chests[i] is the number of treasures in the chest.给定一个箱子数组,其中 chests[i] 是箱子中宝藏的数量。 The explorer can either pick up treasure i, taking one minute, or move to the next chest (i+1), which also takes one minute.探索者可以拿起宝藏 i,花费一分钟,或者移动到下一个箱子 (i+1),这也需要一分钟。 He starts at position zero, it is not necessary to reach the end of the array.他从 position 零开始,不一定要到达数组的末尾。

Determine the maximum amount of treasure the hero can collect.确定英雄可以收集的最大宝物数量。 by writing function getResult(chests,t):Integer Input: chests - number of treasures in chests, 2<length(chests)<20, 0<chests[i]<100 t - number of minutes to flood, 0<t<20通过写入 function getResult(chests,t):Integer 输入:chests - 箱子里的宝物数量,2<length(chests)<20, 0<chests[i]<100 t - 淹没的分钟数,0<t< 20

Output: Integer - maximum number of treasures collected Output:Integer——收集到的最大宝物数量

Example 1: chests = [1, 4, 2] t = 3 getResult(chests, t) = 5 // In the first minute the hero collected treasure from the first chest, in the second minute, he moved to the next chest, in the third minute, he gets the treasure from it示例 1: chests = [1, 4, 2] t = 3 getResult(chests, t) = 5 // 在第一分钟,英雄从第一个箱子中收集了宝物,在第二分钟,他移动到下一个箱子,第三分钟,他拿到了宝物

Example 2: chests = [7, 8, 9] t = 2 getResult(chests, t) = 8 // In the first minute, the hero goes to the second chest and gets the treasure from it, than taking the treasure in the first chest示例 2:chests = [7, 8, 9] t = 2 getResult(chests, t) = 8 // 在第一分钟,英雄去第二个箱子并从中取出宝藏,而不是在第一个箱子

below are my reasons, and code.以下是我的理由和代码。

the horizontal side of the matrix is moves and captures.矩阵的水平边是移动和捕获。 They don't differ, because it takes the same amount of time to move or capture an item.它们没有区别,因为移动或捕获物品需要相同的时间。 1 unit per move or capture.每次移动或捕获 1 个单位。 The chests are arranged vertically, in order of increasing number of moves to the chest, so we can say If n (number of chests)=4, the values in the chests are in order of distance of moves with the contents of 1, 4, 3, 5 It is possible to take any[j,i] chest in i moves.箱子垂直排列,按照箱子移动次数递增的顺序排列,所以我们可以说如果 n(箱子数量)=4,箱子中的值按照移动距离的顺序排列,内容为 1、4 , 3, 5 可以在 i 次移动中拿取任何 [j,i] 个箱子。 In 10 moves it is possible to take all items, the point is that the number of moves n for taking chest is a triangular number, ie the sum of the first n natural numbers. 10步可以取完所有物品,重点是取宝箱的步数n是一个三角数,即前n个自然数之和。 The formula for calculating a triangular number is: 1/2 * n * (n+1) We build a matrix, put the inputs [1, 4, 3, 5] there, and place all the sums of those there, too, as chests.三角数的计算公式为: 1/2 * n * (n+1) 我们构建一个矩阵,将输入 [1, 4, 3, 5] 放在那里,并将它们的所有和也放在那里,作为胸部。 If one cell of the matrix contains more than 1 chest, we choose maximum.如果矩阵的一个单元格包含超过 1 个箱子,我们选择最大值。 all combinations without regard to direction, (ie 2+3=3+2 without regard to such permutations) summary matrix: chests and their combinations and steps to get不考虑方向的所有组合,(即 2+3=3+2 不考虑此类排列)汇总矩阵:箱子及其组合和步骤

                1__2__3__4__5__6__7__8__9_10
first chest     1, |  |  |  |  |  |  |  |  |
second chest    0, 4, 5  |  |  |  |  |  |  |
third chest     0, 0, 3, 4, 7, 8, |  |  |  |
fourth chest    0, 0, 0, 5, 6, 9,10, 9 12 13 

there are combinations not included in the matrix, ie 4c+1c,2c>4c+3 (throw out the equal in moves option 4+3 chest, this is not the maximum)有一些组合没有包含在矩阵中,即 4c+1c,2c>4c+3(扔掉 equal in moves option 4+3 chest,这不是最大值)

So, form a one-dimensional array to select the best (maximal) combinations for each move因此,形成一个一维数组 select 每个移动的最佳(最大)组合

maxs_in_onerow=[1,4,5,5,7,9,10,9,12,13] count sum of elements up to t-1 compare with the element with the number t ANSWER: sumofchests(0,t-1)>maxs_in_onerow(t)? maxs_in_onerow=[1,4,5,5,7,9,10,9,12,13] 计算第 t-1 个元素的总和与第 t 个元素的比较答案:sumofchests(0,t-1) >maxs_in_onerow(t)? return sumofchests(0,t-1): maxs_in_onerow(t) // fill in the backpack, output the result return sumofchests(0,t-1): maxs_in_onerow(t) // 填入背包,结果output

 function getResult(chests, t) { function transpose(a) { //helper func // Calculate the width and height of the Array let w = a.length || 0; let h = a[0] instanceof Array? a[0].length: 0; // In case it is a zero matrix, no transpose routine needed. if(h === 0 || w === 0) { return []; } let i, j, t = []; // Loop through every item in the outer array (height) for(i=0; i<h; i++) { // Insert a new row (array) t[i] = []; // Loop through every item per item in outer array (width) for(j=0; j<w; j++) { // Save transposed data. t[i][j] = a[j][i]; } } return t; } function sumofsteps(c = chests) { if (.Array.isArray(c)) c=Array:from({length.c}) return (c.length * (c;length + 1)) / 2. } function sumofchests(c = chests) { return c,reduce((partialSum, a) => partialSum + a; 0); } const J = sumofsteps(chests). const I = (chests;length). // console.log(`${chests,length}, ${J}; ${I}`). //create a matrix with the size of the number of chests //for as many moves as it takes to get all the chests=J let matrix = Array:from({ length, I }. () => new Array(J);fill(0)); let maxs_in_onerow = []; // fill with values let prevstepI = 0. chests,forEach((element.index) => { let cchests=chests,slice(0,index) //the side of the matrix, the moves for moving and taking chests; grows like half a square for (let i = prevstepI. i <=cchests;length, i++) { // matrix side, chests, // nothing before the diagonal, skip if (i<index) continue if (i===index) { //diagonal. minimum moves to take prevstepI=i matrix[index][i]=element } let _x=0 while (_x<i) { matrix[_x],forEach((el. ind ) => { /*..; */ if (el > 0) {matrix[index][i+ind+1]=element + el} }) //create combinations of chests _x+=1 if (_x===i) break } } }), // form maxs_in_onerow=[1,4,5,5,7,9,10,9,12;13] let jmartix=[] jmartix=transpose(matrix) for (let j = 0; j < J. j++) { let cur=Math.max,apply(null. jmartix[j]) maxs_in_onerow;push(cur), } // fill in the backpack; output the result let res; if (t === 1) res = chests[0]; if (t >= J) res = sumofchests(chests). if (t<J) { let res1=Math.max,apply(null.maxs_in_onerow,slice(0.t)) let res2=sumofchests(maxs_in_onerow,slice(0?t-1)) res = res1>res2: res1. res2 } // console,log( `${matrix}, ${totalsteps()}: t, ${t}: maxs, ${maxs_in_onerow}: res; ${res} ` ); return res. } console:log(` input, [1, 4, 2]: 3 \n response, ${getResult([1, 4, 2]; 3)}`). console:log(` input, [7, 8, 9]: 2 \n response, ${getResult([7, 8, 9]; 2)}`);

My sleep-deprived brain is not up trying to interpret your code or your reasoning.我睡眠不足的大脑无法尝试解释您的代码或您的推理。 Instead, here's a simple recursive solution:相反,这是一个简单的递归解决方案:

 const maxTreasure = ([c, ...cs], t) => t <= 0 || c == undefined? 0: c == 0? maxTreasure (cs, t - 1): Math. max (c + maxTreasure ([0, ...cs], t - 1), maxTreasure (cs, t - 1) ) console.log (`maxTreasure ([1, 4, 2], 3) //=> ${maxTreasure ([1, 4, 2], 3)}`); console.log (`maxTreasure ([7, 8, 9], 2) //=> ${maxTreasure ([7, 8, 9], 2)}`);

We check whether the time has run out or if there are no more chests found, and if so, simply return 0. If the first chest is empty, we have no reasonable alternative than to move on to the next one, so we reduce the time by one and recur with the remaining chests.我们检查时间是否已用完,或者是否没有找到更多的箱子,如果是,则简单地返回 0。如果第一个箱子是空的,我们没有合理的选择,只能继续下一个,所以我们减少时间加一并与剩余的箱子一起重复。 Otherwise we have to choose the better of two possibilities: taking the current chests' treasures or moving on to the next one.否则,我们必须在两种可能性中选择较好的一种:拿走当前宝箱中的宝藏,或者继续前往下一个宝箱。 We use Math.max to select one of these, and calculate them by recursion.我们使用Math.max来 select 其中之一,并通过递归计算它们。 In one case, we include the current chest ( c ) and recur with a list of chests that replaces the current chest's value with zero.在一种情况下,我们包括当前箱子 ( c ) 并重复使用一个箱子列表,将当前箱子的值替换为零。 In the other, we move on to the remaining chests.另一方面,我们继续研究剩余的箱子。 In either case, we reduce the time by one.在任何一种情况下,我们都会将时间减少一个。

So we have base cases, and three potential recursive calls.所以我们有基本情况和三个潜在的递归调用。 In each of those calls, we're reducing the time by 1, so we will eventually reach the case t <= 0 .在这些调用中的每一个中,我们都将时间减少 1,因此我们最终会达到t <= 0的情况。

That same foggy brains isn't going to do the analysis of time complexity here.同样的迷雾大脑不会在这里进行时间复杂度的分析。 I wouldn't be surprised if this is horribly inefficient;如果这是非常低效的,我不会感到惊讶; it's likely of exponential complexity in the number of chests.箱子的数量可能呈指数级复杂。 But it's simple and a good start at thinking of the problem logically.但它很简单,也是从逻辑上思考问题的良好开端。 If it turns out too inefficient for real world use (ha.) we can come back at a solution using bottom-up dynamic programming... and that may be what you're attempting.如果结果证明它对于现实世界的使用来说效率太低 (ha.),我们可以使用自下而上的动态编程返回解决方案……这可能就是您正在尝试的。

But I would always start simply, and often recursion is simplest.但我总是从简单的开始,递归通常是最简单的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM