问题描述
您从给定网格的左上角单元格开始。有些细胞有壁,有些 你可以走路,有些牢房里有苹果。您有时间限制= T,并且您应该至少在T时间之前到达右下角的单元格。找 您可以收集的最大苹果数量。您无法访问手机 两次。 N,M,T
我尝试了很多想法,其中最有前途的是-重新定位问题,因为找到最短的到达目的地的时间至少收集了X个苹果。然后,我们可以对苹果数量进行二进制搜索。 但是我无法确定最近6个小时以来的解决方案。 “你不能两次拜访一个牢房。”这是我的问题。
任何其他想法或提示都会受到赞赏。
解决方法
您尝试过backtracking吗?像这样吗?
// Heuristic: Manhattan distance to end
function dist(y,x,n,m){
return n - y + m - x - 2;
}
function getNext(i,j,m){
const ways = [];
if (i + 1 < n)
ways.push([i+1,j]);
if (i > 0)
ways.push([i-1,j]);
if (j + 1 < m)
ways.push([i,j+1]);
if (j > 0)
ways.push([i,j-1]);
return ways;
}
function f(M,T){
const WALL = 2;
const n = M.length;
const m = M[0].length;
const visited = new Array(n);
for (let i=0; i<n; i++)
visited[i] = new Array(m).fill(0);
let best = 0;
function backtrack(i,t,k){
if (i == n-1 && j == m-1){
best = Math.max(best,k + M[i][j]);
return;
}
for (const [ii,jj] of getNext(i,m)){
if (!visited[ii][jj] &&
M[ii][jj] != WALL &&
t + dist(ii,jj,m) <= T){
visited[ii][jj] = 1;
backtrack(ii,t + 1,k + M[i][j]);
visited[ii][jj] = 0
}
}
}
backtrack(0,0);
return best;
}
var N = 8;
var M = 8;
var T = 14;
var matrix = new Array(N);
for (let i=0; i<N; i++)
matrix[i] = new Array(M).fill(0);
// Apples
matrix[5][5] = 1;
matrix[5][6] = 1;
// Walls
matrix[5][7] = 2;
matrix[5][4] = 2;
matrix[4][4] = 2;
matrix[4][5] = 2;
console.log(f(matrix,T));
matrix[5][4] = 0;
console.log(f(matrix,T));
,
鉴于这些约束,您可以使用一个简单的递归函数来解决问题。
让solve(i,steps,vis)
为函数,其中(i,j)
为当前坐标,time
为剩余时间,vis
为当前访问的节点集。答案将是solve(0,T,[])
。
简单的递归将是(使用伪代码):
def solve(i,vis):
if (i<0 or i>=n or j<0 or j>=m) return -1
if ((i,j) in vis) return -1
if (cell[i][j] == WALL) return -1
if (t==0){
if (i==n-1 and j==m-1) return cell[i][j]
else return -1
}
if (i==n-1 and j==m-1) return cell[i][j]
max_here = cell[i][j]
temp = max(solve(i,j+1,t-1,vis+(i,j)),solve(i,j-1,solve(i+1,t-
1,solve(i-1,j))) #assuming movement in 4 directions
if (temp==-1) return -1 # since none of the neighbours lead to destination
return max_here+temp