- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
给定一个包含每个元素初始状态的矩阵,找到从左上角到右下角到达的最少步数?
条件:
任何元素的初始状态将随机为北、东、南或西之一。在每一步,我们要么不移动任何地方,要么沿着该元素当前状态的方向移动(当然我们永远不会离开矩阵)任何一步都会同时改变矩阵所有元素的状态。状态以顺时针循环方式变化,即从 N -> E -> S -> W。即使我们一步不移动,状态也会发生变化
最佳答案
一个重要的观察是矩阵有 4 个不同的“版本”:每 4 个步骤的倍数,矩阵的内容将完全相同。
您可以将这 4 个矩阵想象成三维(Z 方向),其中 Z 可以是 0、1、2 或 3。将其想象成一个 3D 阵列,其中 4 x 2D 阵列彼此分层。
有了那个 3D 矩阵,“旋转”值的魔力就消失了:这 4 个矩阵中的每一个现在都是静态的。
现在的一个步骤是:
...但在这两种情况下 Z 都变成 (Z+1)%4
目标单元格现在实际上是一组 4 个单元格,因为在您到达右下角时 Z 是什么并不重要。
如果构建此(未加权、有向)图,则可以实现简单的 BFS 搜索。问题解决了。
我想我会为以下示例输入矩阵制作一个小动画:
[
[2, 0, 0, 2, 1, 0, 3],
[0, 0, 0, 2, 0, 0, 1],
[3, 2, 0, 3, 3, 3, 0],
]
数字代表当前可能的方向:0 = 北,1 = 东,2 = 南,3 = 西。
该算法由两个函数组成。一个是 Node 类的方法 shortestPathTo
,它实现了从一个节点到一组目标节点的通用 BFS 搜索。第二个函数 createGraph
会将输入矩阵转换为如上所述的图形。创建此图后,可以在左上角的节点上调用 shortestPathTo
方法。它返回一个 path
,一个要访问的节点数组。
该路径用于制作动画,这是代码的下半部分处理的内容。该部分与算法关系不大,可以忽略。
class Node { // Generic Node class; not dependent on specific problem
constructor(value, label) {
this.value = value;
this.label = label;
this.neighbors = [];
}
addEdgeTo(neighbor) {
this.neighbors.push(neighbor);
}
shortestPathTo(targets) {
targets = new Set(targets); // convert Array to Set
// Standard BFS
let queue = [this]; // Start at current node
let comingFrom = new Map;
comingFrom.set(this, null);
while (queue.length) {
let node = queue.shift();
if (targets.has(node)) { // Found!
let path = []; // Build path from back-linked list
while (node) {
path.push(node);
node = comingFrom.get(node);
}
return path.reverse();
}
for (let nextNode of node.neighbors) {
if (!comingFrom.has(nextNode)) {
comingFrom.set(nextNode, node);
queue.push(nextNode);
}
}
}
return []; // Could not reach target node
}
}
function createGraph(matrix) {
// Convert the matrix and its move-rules into a directed graph
const numCols = matrix[0].length;
const numRows = matrix.length;
const numNodes = numRows * numCols * 4; // |Y| * |X| * |Z|
// Create the nodes
const nodes = [];
for (let y = 0; y < numRows; y++)
for (let x = 0; x < numCols; x++)
for (let z = 0; z < 4; z++) {
let dir = (matrix[y][x] + z) % 4;
nodes.push(new Node({x, y, z, dir}, "<" + x + "," + y + ":" + "NESW"[dir] + ">"));
}
// Create the edges
for (let i = 0; i < nodes.length; i++) {
let node = nodes[i];
let {x, y, z, dir} = node.value;
// The "stand-still" neighbor:
let j = i-z + (z+1)%4;
node.addEdgeTo(nodes[j]);
// The neighbor as determined by the node's "direction"
let dj = 0;
if (dir == 0 && y > 0 ) dj = -numCols*4;
else if (dir == 1 && x+1 < numCols) dj = 4;
else if (dir == 2 && y+1 < numRows) dj = numCols*4;
else if (dir == 3 && x > 0 ) dj = -4;
if (dj) node.addEdgeTo(nodes[j+dj]);
}
// return the nodes of the graph
return nodes;
}
// Sample matrix
let matrix = [
[2, 0, 0, 2, 1, 0, 3],
[0, 0, 0, 2, 0, 0, 1],
[3, 2, 0, 3, 3, 3, 0],
];
// Calculate solution:
const nodes = createGraph(matrix);
const path = nodes[0].shortestPathTo(nodes.slice(-4));
// path now has the sequence of nodes to visit.
// I/O handling for this snippet
const size = 26;
const paint = () => new Promise(resolve => requestAnimationFrame(resolve));
function drawSquare(ctx, x, y, angle) {
ctx.rect(x*size+0.5, y*size+0.5, size, size);
ctx.stroke();
ctx.beginPath();
angle = (270 + angle) * Math.PI / 180;
x = (x+0.5)*size;
y = (y+0.5)*size;
ctx.moveTo(x + 0.5, y + 0.5);
ctx.lineTo(x + Math.cos(angle) * size * 0.4 + 0.5, y + Math.sin(angle) * size * 0.4 + 0.5);
ctx.stroke();
}
function drawBall(ctx, x, y) {
x = (x+0.5)*size;
y = (y+0.5)*size;
ctx.beginPath();
ctx.arc(x, y, size * 0.2, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
}
async function draw(ctx, matrix, time=0, angle=0, curX=0, curY=0) {
await paint();
time = time % 4;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
for (let y = 0; y < matrix.length; y++) {
for (let x = 0; x < matrix[0].length; x++) {
drawSquare(ctx, x, y, (matrix[y][x] + time) * 360 / 4 - angle);
}
}
drawBall(ctx, curX, curY);
}
async function step(ctx, matrix, time, curX, curY, toX, toY) {
for (let move = 100; move >= 0; move-=5) {
await draw(ctx, matrix, time, 90, toX + (curX-toX)*move/100, toY + (curY-toY)*move/100);
}
for (let angle = 90; angle >= 0; angle-=5) {
await draw(ctx, matrix, time, angle, toX, toY);
}
}
async function animatePath(ctx, path) {
for (let time = 1; time < path.length; time++) {
await step(ctx, matrix, time, path[time-1].value.x, path[time-1].value.y, path[time].value.x, path[time].value.y);
}
}
const ctx = document.querySelector("canvas").getContext("2d");
draw(ctx, matrix);
document.querySelector("button").onclick = () => animatePath(ctx, path);
<button>Start</button><br>
<canvas width="400" height="160"></canvas>
您可以在代码中更改matrix
的定义来尝试其他输入。
关于algorithm - 如何解决达到矩阵问题结束所需的最少步骤?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57125529/
我正在编写一个类,我想知道哪一对方法更适合描述流程周期: start() -> stop() start() -> end() start() -> finish() 基本上这些方法将在执行任务之前和
对于 Android 小部件类名称是否应以“View”、“Layout”或两者都不结尾,是否存在模式或命名约定? 最佳答案 如果该类扩展了 View(或在其层次结构中扩展了 View),那么它应该以“
我正在尝试找到一个插件,该插件将使用 Verilog 突出显示匹配的开始/结束语句。 VIM 让它与花括号/括号一起工作,但它不能与它的开始/结束一起工作。我希望 VIM 突出显示正确的开始到正确的结
给出以下代码: % Generate some random data n = 10; A = cell(n, 1); for i=1:n A{i} = timeseries; A{i
我需要知道是否可以检测输入何时开始聚焦以及何时结束焦点 HTML 代码: JQuery 代码(仅示例我如何需要它): $('.datas').on('focusStart', alert("fo
所以我一直在思考一款游戏的想法,一款需要穿越时空的游戏。因此,我编写了一个 JFrame 来显示螺旋的 .gif,但它并没有在对话框显示时结束,而是保留在后台。我可以解决这个问题吗? import j
给出以下使用多线程的 Java 示例: import java.util.concurrent.*; public class SquareCalculator { private Ex
好吧,我有一个 do-while 循环,应该在使用点击“q”时结束,但它给了我错误消息,请帮忙。 package Assignments; import java.util.*; public cla
我如何有选择地匹配开始 ^或结束 $正则表达式中的一行? 例如: /(?\\1', $str); 我的字符串开头和结尾处的粗体边缘情况没有被匹配。我在使用其他变体时遇到的一些极端情况包括字符串内匹配、
我试图让程序在总数达到 10 时结束,但由于某种原因,我的 while 循环在达到 10 时继续计数。一旦回答了 10 个问题,我就有 int 百分比来查找百分比。 import java.util.
jQuery 中的 end() 函数将元素集恢复到上次破坏性更改之前的状态,因此我可以看到它应该如何使用,但我已经看到了一些代码示例,例如:on alistapart (可能来自旧版本的 jQuery
这个问题在这里已经有了答案: How to check if a string "StartsWith" another string? (18 个答案) 关闭 9 年前。 var file =
我正在尝试在 travis 上设置两个数据库,但它只是在 before_install 声明的中途停止: (END) No output has been received in the last 1
我创建了一个简单的存储过程,它循环遍历一个表的行并将它们插入到另一个表中。由于某种原因,END WHILE 循环抛出缺少分号错误。所有代码对我来说都是正确的,并且所有分隔符都设置正确。我只是不明白为什
您好,我正在使用 AVSpeechSynthesizer 和 AVSpeechUtterance 构建一个 iOS 7 应用程序,我想弄清楚合成何时完成。更具体地说,我想在合成结束时更改播放/暂停按钮
这是我的代码,我试图在响应后显示警报。但没有显示操作系统警报 string filepath = ConfigurationManager.AppSettings["USPPath"].ToStri
我想创建一个循环,在提供的时间段、第一天和最后一天返回每个月(考虑到月份在第 28-31 天结束):(“function_to_increase_month”尚未定义) for beg in pd.d
我目前正在用 Python 3.6 为一个骰子游戏编写代码,我知道我的编码在这方面有点不对劲,但是,我真的只是想知道如何开始我的 while 循环。游戏说明如下…… 人类玩家与计算机对战。 玩家 1
所以我已经了解了如何打开 fragment。这是我的困境。我的 view 旁边有一个元素列表(元素周期表元素)。当您选择一个元素时,它会显示它的信息。 我的问题是我需要能够从(我们称之为详细信息 fr
我想检测用户何时停止滚动页面/元素。这可能很棘手,因为最近对 OSX 滚动行为的增强创造了这种新的惯性效应。是否触发了事件? 我能想到的唯一其他解决方案是在页面/元素的滚动位置不再改变时使用间隔来拾取
我是一名优秀的程序员,十分优秀!