zoukankan      html  css  js  c++  java
  • [NOIP2013]华容道 题解

    [NOIP2013]华容道

    首先是一种比较显然的做法。

    整个棋盘,除了起点,终点和空格,其他的方块是等价的。

    对于终点,它始终不会变化,如果搜到终点结束搜索即可,所以我们不需要考虑终点。

    所以需要考虑的是空格的位置和起点方块的位置。

    定义$f(i1,j1,i2,j2)$为

    空格所在坐标$(i1,j1)$  起点坐标$(i2,j2)$。

    对于每一步,可以移动空格周围的一个可移动棋子,将它与空格位置交换。其实等价于空格移动到和空格相邻的棋子。如果该棋子是起点,则将起点更新到原来空格的坐标。

    使用bfs,每次步数加一,队列内的状态步数满足单调,第一次得到(区别于dijkstra,不是第一次取出)的任何一个状态就是最优。当第一次得到起点坐标等于终点坐标时,直接返回答案。

    如果到最后也没有得到起点坐标等于终点坐标,返回-1表示无解。

    这一种做法实际上遍历了可能得到答案的所有情况,应该不是正解。

    复杂度O(n²m²q),期望得分80,不太好剪枝。

     

     

     这道题的正解使我想到了另一道题。进阶指南0x25节中推箱子一题。也使用了bfs。

    空格到处乱跑,其实是没有意义的,如果它不在起点的周围四个格子,它永远无法使起点靠近终点。

    所以我们固定空格在起点的周围四个点,并用当前的状态去更新以后的状态。

    每次取出,一种更新方式是直接与起点交换,二是将该位置交换到起点的另一个方向。

    因为每次的增量不保证相同,这一次不保证第一次得到是最优了,所以要使用spfa或者dijkstra来跑最短路。

    如果像推箱子一样双重bfs,那么你一定还是会tle,甚至比以前跑得更慢。因为复杂度一点都没有降下来。

    问题在这一道题是多测,解决办法是预处理,只要O(n²m²)对每一个点更新一下到其他点的距离即可。

  • 相关阅读:
    linux反汇编
    Java中UML图
    Java设计模式_创建型模式_单例模式
    Javadoc注释的用法
    VIM使用技巧1
    手动破解的 Linux下的Maltab 2014b
    让vim的在输入模式下现实光标不同
    Vim 自动补全成对的括号和引号
    MAMP:在 OSX 中搭建 Apache, MySQL, PHP 环境并本地安装、调试 WordPress
    MAC+iTerm定制目录显示颜色和提示符
  • 原文地址:https://www.cnblogs.com/skyh/p/11200785.html
Copyright © 2011-2022 走看看