簡體   English   中英

這個背包問題的解決方案有什么問題?

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

我知道這更多的是解決問題而不是編碼問題,所以如果這篇文章違反了這里的任何規則,我深表歉意,但是有人知道如何最好地向 go 發送這方面的信息嗎?

我正在嘗試解決問題,但我的代碼中存在邏輯錯誤,或者說我沒有考慮所有條件,請告訴我如何找到它。

問題:一位冒險家發現自己身處充滿寶藏的地牢中。 然而,在進入之前,他啟動了一個陷阱,在 t 分鍾內,這個陷阱將淹沒整個房間。 給定一個箱子數組,其中 chests[i] 是箱子中寶藏的數量。 探索者可以拿起寶藏 i,花費一分鍾,或者移動到下一個箱子 (i+1),這也需要一分鍾。 他從 position 零開始,不一定要到達數組的末尾。

確定英雄可以收集的最大寶物數量。 通過寫入 function getResult(chests,t):Integer 輸入:chests - 箱子里的寶物數量,2<length(chests)<20, 0<chests[i]<100 t - 淹沒的分鍾數,0<t< 20

Output:Integer——收集到的最大寶物數量

示例 1: chests = [1, 4, 2] t = 3 getResult(chests, t) = 5 // 在第一分鍾,英雄從第一個箱子中收集了寶物,在第二分鍾,他移動到下一個箱子,第三分鍾,他拿到了寶物

示例 2:chests = [7, 8, 9] t = 2 getResult(chests, t) = 8 // 在第一分鍾,英雄去第二個箱子並從中取出寶藏,而不是在第一個箱子

以下是我的理由和代碼。

矩陣的水平邊是移動和捕獲。 它們沒有區別,因為移動或捕獲物品需要相同的時間。 每次移動或捕獲 1 個單位。 箱子垂直排列,按照箱子移動次數遞增的順序排列,所以我們可以說如果 n(箱子數量)=4,箱子中的值按照移動距離的順序排列,內容為 1、4 , 3, 5 可以在 i 次移動中拿取任何 [j,i] 個箱子。 10步可以取完所有物品,重點是取寶箱的步數n是一個三角數,即前n個自然數之和。 三角數的計算公式為: 1/2 * n * (n+1) 我們構建一個矩陣,將輸入 [1, 4, 3, 5] 放在那里,並將它們的所有和也放在那里,作為胸部。 如果矩陣的一個單元格包含超過 1 個箱子,我們選擇最大值。 不考慮方向的所有組合,(即 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 

有一些組合沒有包含在矩陣中,即 4c+1c,2c>4c+3(扔掉 equal in moves option 4+3 chest,這不是最大值)

因此,形成一個一維數組 select 每個移動的最佳(最大)組合

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) // 填入背包,結果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)}`);

我睡眠不足的大腦無法嘗試解釋您的代碼或您的推理。 相反,這是一個簡單的遞歸解決方案:

 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)}`);

我們檢查時間是否已用完,或者是否沒有找到更多的箱子,如果是,則簡單地返回 0。如果第一個箱子是空的,我們沒有合理的選擇,只能繼續下一個,所以我們減少時間加一並與剩余的箱子一起重復。 否則,我們必須在兩種可能性中選擇較好的一種:拿走當前寶箱中的寶藏,或者繼續前往下一個寶箱。 我們使用Math.max來 select 其中之一,並通過遞歸計算它們。 在一種情況下,我們包括當前箱子 ( c ) 並重復使用一個箱子列表,將當前箱子的值替換為零。 另一方面,我們繼續研究剩余的箱子。 在任何一種情況下,我們都會將時間減少一個。

所以我們有基本情況和三個潛在的遞歸調用。 在這些調用中的每一個中,我們都將時間減少 1,因此我們最終會達到t <= 0的情況。

同樣的迷霧大腦不會在這里進行時間復雜度的分析。 如果這是非常低效的,我不會感到驚訝; 箱子的數量可能呈指數級復雜。 但它很簡單,也是從邏輯上思考問題的良好開端。 如果結果證明它對於現實世界的使用來說效率太低 (ha.),我們可以使用自下而上的動態編程返回解決方案……這可能就是您正在嘗試的。

但我總是從簡單的開始,遞歸通常是最簡單的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM