Facebook 示例拼图:河内塔

2024-01-10

这是 Facebook 招聘样本测试中的一个问题。

有 K 个钉子。当从桩的底部到顶部观察时,每个桩可以按半径递减的顺序容纳圆盘。有N个圆盘,半径为1到N;给定钉子的初始配置和钉子的最终配置,输出从初始配置转换到最终配置所需的移动。您需要以最少的移动次数完成转换。

移动包括拾取任何一个钉子的最上面的圆盘并将其放置在任何其他钉子的顶部。 在任何时间点,必须保持所有桩的半径递减特性。

限制条件:

1

3

输入格式:

N K

第 2 行包含 N 个整数。每个整数都在 1 到 K 的范围内,其中第 i 个整数表示在初始配置中半径为 i 的圆盘所在的栓钉。

第三行表示最终配置,格式与初始配置类似。

输出格式:

第一行包含 M - 完成变换所需的最少移动次数。

下面的 M 行通过要选取的桩号和要放置的桩号来描述移动。 如果有多个解决方案,则输出其中任何一个就足够了。你可以假设,总是有一个少于 7 步的解决方案,并且初始配置不会与最终配置相同。

输入示例#00:

2 3

1 1

2 2

示例输出#00:

3

1 3

1 2

3 2

输入示例#01:

6 4

4 2 4 3 1 1

1 1 1 1 1 1

示例输出#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;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Facebook 示例拼图:河内塔 的相关文章

  • Oauth 2:access_token 是用户的唯一密钥吗?

    一个用户之后与 Facebook 连接 https developers facebook com docs authentication Facebook 回应access token 我可以假设这个吗access token将始终保持不
  • Python 将字符串组合成尽可能短的字符串?

    如果我有一个字符串列表 我想将它们组合成一个具有重叠字符的字符串 如果没有剩余的重叠字符串 请将其添加到末尾 这是一个过于简化的版本 input one two output twone 我正在寻找一种方法来对输入列表中的任意数量的字符串执
  • 将您的应用程序链接到现有页面

    我搜索了又搜索 似乎找不到任何与此相关的信息 我们有一个 Facebook 页面 facebook com companyname 我们在 Facebook 上也有一个应用程序 apps facebook com companyname 我
  • Facebook广告,将客户页面添加到业务经理

    我想要做的是能够从我的 Facebook 帐户创建和发布 FB 广告 并使用 Facebook api 将其发布到其他用户的 Facebook 页面上 用户可以安装我的应用程序 该应用程序将要求管理页面 业务管理权限以及其他一些所需的权限
  • 通过 Facebook 图 api 点赞帖子

    你好 我对 facebook PHP SDK 没有什么问题 我想通过 facebook PHP SDK 点赞帖子或其他内容 我正在执行此代码 我认为它应该是正确的 但显然它不起作用 给定的错误代码是的 PHP SDK不知道这种POST请求
  • FB SDK 3.0 我是否需要扩展访问令牌还是自动的?

    基于http developers facebook com roadmap offline access removal http developers facebook com roadmap offline access remova
  • std::__gcd 和 std::gcd 有什么区别?

    Many https www geeksforgeeks org stdgcd c inbuilt function finding gcd websites https codeforces com submissions Madiyar
  • 如何从 Unix 命令行递归解压目录及其子目录中的档案?

    The unzip命令没有递归解压缩档案的选项 如果我有以下目录结构和档案 Mother Loving zip Scurvy Sea Dogs zip Scurvy Cures Limes zip 我想将所有档案解压缩到与每个档案同名的目录
  • Facebook API:确定 Facebook 页面是否已发布/未发布

    使用图形 API 检查 Facebook 页面是否已发布或未发布的可靠方法是什么 我目前这样做 http graph facebook com http graph facebook com page id 并检查返回值是否为 false
  • Facebook oauth/access_token 丢失

    不知道我是否错过了什么 但就这样 我正在尝试为我的应用程序获取 access token 以便它可以在 facebook 上查找某些公共群组的事件 而无需用户登录 我试图从中获取 access token 这将返回一个字符串 access
  • Safari 会话变量中具有多个页面的 Facebook Iframe 应用程序不持久

    我有一个 facebook Iframe 应用程序 其中包含多个 PHP 页面 我有一些链接相对于我的 iframe 文件夹 内的文件 iframe 内的会话变量存在一些问题 我设置了一些会话变量 但它们不会从一个页面持续到另一个页面 这确
  • 如何发现“贪婪”算法?

    我正在读一本关于 贪婪 算法 但我很难发现它们解决真正的 顶级程序员 问题 If I know给定的问题可以用 贪婪 算法来解决 因此编写解决方案非常容易 然而 如果我没有被告知这个问题是 贪婪的 我就无法发现它 用 贪婪 算法解决的问题有
  • 数字总和直到作为输入给出的数字

    如果给出一个数字作为输入 则找到该数字之前所有数字的总和 例如输入 11 则答案为 1 2 9 1 0 1 1 蛮力方法是计算所有小于某个数字的数字的数字之和 我已经实现了该方法 我想知道是否有其他方法可以在不实际计算每个数字的数字之和的情
  • Facebook LoginActivity 未正确显示

    我有一个使用 Facebook 登录的应用程序 我有 FacebookSDK 并且使用 com facebook LoginActivity 问题是 在 10 英寸平板电脑上 当显示软键盘时 活动无法正确显示 我使用的是 Samsung G
  • 将两个大数作为字符串相除,而不使用java中的Bignumbers

    我需要在不使用 Biginteger 的情况下划分两个大整数 因为数字不能存储在原始类型中 因为我需要从给定的字符串中逐个字符地执行此操作 我已经创建了一个名为 BigNumber 的类 用这个类我可以 Add multiply 比较两个内
  • 给定一个零索引数组 & 该数组的平衡索引[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 给出一个由 N 个整数组成的零索引数组 A 该数组的平衡索引是任何整数 P 满足 0 P 例如 考虑以下由 N 8 个元素组成的数组
  • 让 prerender.io 与 Facebook 爬虫(maven、GAE)一起使用?

    我有一个 angularjs 应用程序 我想在 Facebook 上分享页面 这是通过元标签处理的 https developers facebook com docs sharing best practices https develo
  • 查找数组中的组合

    我在java中有一个像这样的二维数组 transmission communication tv television approach memorycode methodact 我需要获得所有组合 例如 transmission appr
  • 循环中的递归算法复杂度(运行时间)

    我想了解您对如何检测以下递归算法的 T n 运行时间 的意见 Charm 是一种用于发现事务数据库中频繁闭项集的算法 频繁闭项集列表是在一组交易 tids 中多次出现的频繁项 例如面包和牛奶是经常一起购买的物品 它们是通过将索引为 i 的当
  • Lisp 中的十进制到二进制 - 制作非嵌套列表

    当达到我的递归情况时 我使用list将未来结果附加到当前结果 但由于递归 我最终得到一个嵌套列表 当我有一个导致递归超过五次的数字时 这会导致错误 任何想法如何我可以在一个简单的非嵌套列表中获得结果 例如 CL 用户 100 8 gt BI

随机推荐

  • 按值对字典键进行排序,然后按字母顺序对具有相同值的键进行排序

    我知道标题中没有很好地解释 所以我会尽力在这里做得更好 我想按字典的键各自的值对它们进行排序 然后按字母顺序对具有相同值的所有键进行排序 最好不使用模块 最好的方法是什么 python 是否会自动执行此操作 如下所示 sorted dict
  • Azure 资源管理器模板 HostingEnvironment

    我从azure gallery下载了Web App MySQL的arm模板 https gallery azure com artifact https gallery azure com artifact 20151001 Microso
  • bash 获取文件的父目录

    如何获取文件的父目录 我希望它对所有类型的名称都是安全的 path to my file absolute path to my file rf no preserve root whatever test zip symbolic lin
  • TRUNCATE 和 DELETE 之间的区别? [复制]

    这个问题在这里已经有答案了 TRUNCATE and DELETE命令执行相同的工作 在这两种情况下都对数据进行操作 那么为什么DELETE命令属于 DML 命令并且TRUNCATE命令属于 DDL 命令吗 DELETE DELETE 是一
  • Jenkins 发现找不到 ssh 密钥 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 当我以 jenkins 用户身份登录时 我在 ssh id rsa pub 中有一个 ssh 密钥 我已将其正确导入到 bitbucket 中 并且它
  • 从头开始水平视差滚动 - 无插件 (jQuery)

    有谁知道我是否可以找到有关如何通过js表单scratch 即无插件 进行水平视差滚动的教程 或者可以给我一个例子 我花了很多时间谷歌搜索 但只能找到使用插件的教程 我想从头开始做的原因是因为我想完美地理解视差的真正工作原理 我不介意使用jQ
  • 使用 XSLT 删除节点后消除空行

    我正在使用 XSLT 在 XML 文档中进行非常简单的转换 我只想删除所有具有特定名称的元素节点 碰巧在我的源文档中 所有这些节点都位于文档的末尾 但是在转换之后 虽然这些节点按照我的预期消失了 但在它们的位置上有很多空行 这严格来说是一个
  • WPF 中心子窗口无法使用 sizetocontent

    如果我设置SizeToContent to WidthAndHeight then WindowStartupLocation CenterOwner 不能正常工作 新窗口的中心不是位于其父窗口的中心 而是看起来更像是子窗口的左上角位于父窗
  • 解决 Unity 依赖关系问题

    当我尝试解决我的工作单元时 我收到此错误 IUnitOfWork 类型没有可访问的构造函数 但是 只有当我将 unitOfWork 的 LifetimeManager 设置为 PerResolveLifetimeManager 时 才会发生
  • 如何从 Windows 命令行启动 Git Bash?

    我希望这是一个简单的问题 但我还没有找到答案 我想从 Windows 批处理文件启动 Git Bash 这是我到目前为止所尝试的 从 Windows 7 开始按钮启动 Git Bash 使用 CTRL ALT DEL 将进程识别为 sh e
  • 我如何改进这个 C# 随机方法?

    我想我已经决定将其作为随机列表的最简单且可进行单元测试的方法 但有兴趣听到任何改进 public static IList
  • 我的 Android AChartEngine 已经可以工作了,但是如何让它看起来更好呢?

    我想标题已经解答了我的大部分问题 但让我们详细介绍一下背景 我有一个主要针对平板电脑的 Android 应用程序 它将在 TimeCharts 中显示一些不同的实时数据 因此 我已经有一个与数据源通信的服务 该数据源获取数据 解析数据并将值
  • 这里有人使用Linux主机/VMWare/VirtualKD调试环境吗?

    有没有人有过成功的经验虚拟KD http virtualkd sysprogs org在运行 VMWare Workstation 8 带有 Win7 客户机 的 Linux 主机上进行设置 尽管事实上有很多关于 VirtualKD 的 速
  • 选择/插入/更新表字段数据时修剪空格(前导和尾随)是一个好习惯吗?

    假设空格在字段数据中并不重要 那么在插入 更新或从表中选择数据时修剪空格是一个好习惯吗 我想象不同的数据库以不同的方式实现空格处理 因此为了避免这种头痛 我认为我应该禁止任何字段数据中的前导和尾随空格 你怎么认为 我认为这是一个很好的做法
  • Android 中 EditText 的不同颜色

    我正在尝试使 EditText 的文本具有多种颜色 例如 如果我的文本是 It is a good day 是否可以将句子的 It is a 部分设置为绿色 其余部分设置为红色 我用类似的东西使我的颜色的某些部分变成绿色 final Str
  • 使用 Ninject 具有多个参数的构造函数

    我正在尝试使用Ninject http www ninject org 作为 IoC 容器 但无法理解如何创建在构造函数中具有超过 1 个参数的类的实例 基本上 我有一个用于在 PCL 库中进行身份验证的服务接口 及其在 WP8 项目中的实
  • 我应该使用什么协议来进行快速命令/响应交互?

    我需要建立一个用于快速命令 响应交互的协议 我的直觉告诉我只需将一个简单的协议与 CRLF 分隔的 ascii 字符串拼凑在一起 就像 SMTP 或 POP3 的工作方式一样 如果我需要保护它 则可以通过 SSH SSL 对其进行隧道传输
  • PHP 是否优化尾递归?

    我写了一小段代码 我相信如果尾递归被优化的话应该会成功 但是它炸毁了堆栈 我应该得出 PHP 没有优化尾递归的结论吗 function sumrand n sum if n 0 return sum else return sumrand
  • C#,后台工作者

    我有一个示例 WinForms 应用程序 它使用BackgroundWorker成分 它工作正常 但是当我点击Cancel按钮取消后台线程 但它不会取消线程 当我击中Cancel呼叫按钮 CancelAsync 方法 然后在RunWorke
  • Facebook 示例拼图:河内塔

    这是 Facebook 招聘样本测试中的一个问题 有 K 个钉子 当从桩的底部到顶部观察时 每个桩可以按半径递减的顺序容纳圆盘 有N个圆盘 半径为1到N 给定钉子的初始配置和钉子的最终配置 输出从初始配置转换到最终配置所需的移动 您需要以最