- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
这是来自 Facebook 招聘样本测试的问题。
有K个钉子。当从钉子的底部到顶部看时,每个钉子可以按半径递减的顺序固定圆盘。有 N 个圆盘,半径为 1 到 N;给定钉子的初始配置和钉子的最终配置,输出从初始配置转换为最终配置所需的移动。您需要以最少的移动次数完成转换。
移动包括拾取任何一个桩子的最上面的圆盘并将其放在任何其他桩子的顶部。在任何时候,都必须保持所有钉子的递减半径特性。
Constraints:
1<=N<=8
3<= K<=5
Input Format:
NK
第二行包含 N 个整数。每个整数都在 1 到 K 的范围内,其中第 i 个整数表示初始配置中半径为 i 的圆盘所在的桩。
第三行以类似于初始配置的格式表示最终配置。
Output Format:
第一行包含 M - 完成转换所需的最少移动数。
接下来的 M 行描述了一个移动,通过一个要从中选择的 Hook 编号和一个要放置的 Hook 编号。如果有多个解决方案,输出其中任何一个就足够了。您可以假设,总有一个少于 7 步的解决方案,并且初始配置不会与最终配置相同。
Sample Input #00:
2 3
1 1
2 2
Sample Output #00:
3
1 3
1 2
3 2
Sample Input #01:
6 4
4 2 4 3 1 1
1 1 1 1 1 1
Sample Output #01:
5
3 1
4 3
4 1
2 1
3 1
讨论这个问题的解决方案没有什么坏处,因为它是一个示例问题。
经典的汉诺塔问题的解决方案非常易于编写代码:
void hanoi(char s, char i, char d, int n)
{
if(n>0)
{
hanoi(s, d, i, n-1);
cout<<s<<":"<<d<<endl;
hanoi(i, s, d, n-1);
}
}
以上内容也可以扩展到河内的一般“k”钉塔。但是,事实证明,这些知识对于设计这个示例难题的解决方案毫无用处。对于将来如何处理此类问题和类似问题有什么建议吗?
最佳答案
这是我的动态规划解决方案,最多可在 O(K^N) 步中找到最佳移动顺序,它在 K = 5、N = 8 的情况下运行不到一秒。由于懒惰,我对输入数据进行了硬编码.
它是一个通过状态空间的 BFS,永远不会访问同一个状态两次。然后通过从头到头回溯得到实际路径(这部分与最优序列的长度成线性关系)。基本上,它是“通过迷宫的最短路径”算法,但“迷宫”是问题的状态空间,起始“位置”是初始状态,结束“位置”是期望状态。
许多类似的问题都可以通过这种方式解决,只要您可以定义一个有限状态空间,您的目标是最小化两个状态之间的“距离”,以及一种计算可以从状态移动到哪些状态的方法当前状态。
例如,任意数量的“传教士和食人者”问题都可以用相同的算法解决。
此外,如果您需要“所有最优解”而不是“任何最优解”,则很容易修改算法以提供它们。
class Program
{
static int N = 8;
static int K = 5;
static List<int> StartState = new List<int> { 3, 3, 2, 1, 4, 1, 5, 2 };
static List<int> EndState = new List<int> { 1, 4, 2, 2, 3, 4, 4, 3 };
static LinkedList<int> StateQueue = new LinkedList<int>();
static int[] MovesToState = new int[(int)Math.Pow(K, N)];
static void Main(string[] args)
{
for (int i = 0; i < StartState.Count; i++)
{
StartState[i]--;
EndState[i]--;
}
int startStateIndex = StateToNum(StartState);
int endStateIndex = StateToNum(EndState);
for (int i = 0; i < MovesToState.Length; i++)
MovesToState[i] = -1;
MovesToState[startStateIndex] = 0;
StateQueue.AddFirst(startStateIndex);
while (StateQueue.Count > 0 && MovesToState[endStateIndex] == -1)
{
var legalMoves = LegalMoves(StateQueue.Last.Value);
foreach (var newStateIndex in legalMoves)
{
int currMoves = MovesToState[StateQueue.Last.Value];
if (MovesToState[newStateIndex] == -1)
{
MovesToState[newStateIndex] = currMoves + 1;
StateQueue.AddFirst(newStateIndex);
}
}
StateQueue.RemoveLast();
}
var currStateIndex = endStateIndex;
var moves = new List<Tuple<int, int>>();
while (currStateIndex != startStateIndex)
{
var legalMoves = LegalMoves(currStateIndex);
int currMoves = MovesToState[currStateIndex];
foreach (var prevStateIndex in legalMoves)
{
if (MovesToState[prevStateIndex] == MovesToState[currStateIndex] - 1)
{
var currState = NumToState(currStateIndex);
var prevState = NumToState(prevStateIndex);
for (int i = 0; i < N; i++)
{
if (currState[i] != prevState[i])
{
moves.Add(new Tuple<int, int>(prevState[i] + 1, currState[i] + 1));
currStateIndex = prevStateIndex;
break;
}
}
}
}
}
Console.WriteLine(MovesToState[endStateIndex]);
moves.Reverse();
foreach (var move in moves)
{
Console.WriteLine("{0} {1}", move.Item1, move.Item2);
}
Console.Read();
}
static List<int> LegalMoves(int stateIndex)
{
var legalMoves = new List<int>();
var state = NumToState(stateIndex);
int[] minOnPeg = new int[K];
for (int i = 0; i < minOnPeg.Length; i++)
minOnPeg[i] = N;
for (int i = 0; i < N; i++)
for (int j = 0; j < K; j++)
if (state[i] == j && i < minOnPeg[j])
minOnPeg[j] = i;
bool[] isTop = new bool[N];
for (int i = 0; i < isTop.Length; i++)
isTop[i] = false;
for (int i = 0; i < K; i++)
if (minOnPeg[i] < N)
isTop[minOnPeg[i]] = true;
for (int i = 0; i < N; i++)
{
if (!isTop[i])
continue;
for (int j = 0; j < K; j++)
{
if (minOnPeg[j] <= i)
continue;
var tmp = state[i];
state[i] = j;
var newStateIndex = StateToNum(state);
legalMoves.Add(newStateIndex);
state[i] = tmp;
}
}
return legalMoves;
}
static int StateToNum(List<int> state)
{
int r = 0;
int f = 1;
foreach (var peg in state)
{
r += f * peg;
f *= K;
}
return r;
}
static List<int> NumToState(int num)
{
var r = new List<int>();
for (int i = 0; i < N; i++)
{
r.Add(num % K);
num = num / K;
}
return r;
}
}
关于Facebook 示例拼图 : Towers of Hanoi,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16601701/
在我的一个 Ansible 剧本中,我使用 vmware_guest在 vCenter Server 上创建 VM 的模块。当我使用作业模板在 Ansible Tower 上运行 Playbook 并
Ansible 塔中是否有办法暂停工作流模板执行并等待用户在完成作业模板后提供某种输入,例如“批准”或“拒绝”,然后继续下一个作业模板? 我正在尝试构建一个将有 5 个作业模板的工作流,但我希望在第二
我的目录结构设置为 playbooks 目录位于 /var/lib/awx/projects/ 下角色是剧本下的符号链接(symbolic link)。 我需要角色的符号链接(symbolic lin
这是“破解编码面试”一书中的问题: 一个马戏团正在设计一个塔套路,其中的人站在彼此的塔顶上肩膀。出于实用和审美的原因,每个人都必须比他或她下面的人既矮又轻。给定马戏团中每个人的高度和体重,编写一个方法
问候大家, 我最近开始搞乱 Ansible(特别是 Ansible Tower)。 我在我的剧本中使用安全值时遇到了一个问题,更准确地说,我不明白如何正确使用它。 与 Chef-Infra 相比,您可
下面的代码解决了 hanoi 使用预定义函数 moveLOD、swapLOI 和 swapLID 返回 Action 列表的问题。 MoveLOD:将 1 个圆盘从第一个位置移动到三元组第三个位置中的
如您所知,有一些解决汉内塔的方法,但它们要求开始时所有磁盘都在一个塔中。 现在我想知道有什么办法可以解决这个问题,开始时磁盘已经随机分布在塔中。 最佳答案 是的,它仍然是可解的(假设小磁盘之上没有大磁
这是来自 Facebook 招聘样本测试的问题。 有K个钉子。当从钉子的底部到顶部看时,每个钉子可以按半径递减的顺序固定圆盘。有 N 个圆盘,半径为 1 到 N;给定钉子的初始配置和钉子的最终配置,输
尝试通过 REST API 启动工作流程并传递额外变量供剧本使用,但返回的正文显示提供的变量已放入 ignored_fields 部分。 使用 POSTMAN 和 CURL 运行模板都返回相同的结果
在 Git Tower 内部,我存储了大约 26 个文件。但是,当我尝试将存储应用回我的工作树时,我收到有关尾随空格的错误。 我怎样才能成功应用存储,绕过该错误? 完整的错误信息如下: :87: tr
我自己和同事都有相同版本的 Git Tower,当他专注于未提交的更改并点击空格键时,文件会暂存以进行提交。当我按下空格键时,什么也没有发生。那是怎么回事?我喜欢我的热键!空格键会在我的浏览器中选中复
我正在尝试使用此 python 脚本获取/创建 OAuth2 访问 token : import requests import json token_url = 'https://mytower.e
我正在 Tower 服务器中执行以下 POST: http:///api/v2/job_templates/10/launch/ Headers: Content-Type:application/j
我的讲师在测试中向我们提出了以下问题: “给出以下代码: int count=0; static void towersOfhanoi(int n, char source, char target,
我使用 Ansible Vault 来加密存储敏感数据的文件。 在我的编排脚本中,下面提到了运行剧本的命令。 ansible-playbook -i hosts -vvv Playbook.yml -
我理解递归的概念以及它如何与每次调用叠加。但我无法解释当有两个函数调用由 printf 命令分隔时,递归调用如何工作并打印。谁能向我解释一下这个递归调用是如何工作的? 我找到了一个关于名为“Tower
我想知道一种方法或方法来找到手机连接到的小区的位置(GSM one) 这是我的课: package com.example.signal; import java.io.File; import ja
这个问题在这里已经有了答案: Tower of Hanoi: Recursive Algorithm (29 个答案) 关闭 8 年前。 我是 Python 的新手,目前正在学习有关汉诺塔和递归的教
我正在我的 Mac 上试用 Tower 和 Sourcetree GUI,我有两个非常基本的问题: 这些 GUI 是安装 Git 可执行文件还是使用安装在我的 Mac 上的 Git? Git 在我的
我已经在 Mac Finder 中重新组织了我的存储库的文件夹结构,现在当我打开 Git Tower 时,它通知我无法找到这些存储库。我明白这一点,但我正在尝试弄清楚如何从应用程序内部更新存储库的位置
我是一名优秀的程序员,十分优秀!