NOIP2013华容道——史上最强题解

[解题思路]

解题思路

这道题的数据范围是n≤30,所以,我们可以看到,裸的O(n4) 的宽搜对于求解q较小的情况是无压力的,但是在q大的情况下,毫无疑问会时间超限,明显,在q较大的情况下,我们需要将每次宽搜中重复搜索的冗余信息除去,所以我们可以先分析题目性质:(这里称要移动的棋子为目标棋子)

首先,如果要移动目标棋子,那么我们首先必须要将空格移到该棋子的上下左右四个方

向上相邻位置之一,然后才可以移动该棋子。 然后,我们分析该棋子移动时候的性质: 棋子每次可以移动,仅当空格位于其相邻位置的时候,每次移动完棋子,空格总会在棋

子相邻的位置,那么我们发现,对于棋子在某一位置,然后空格又在其四个方向上某一

相邻位置时,棋子要想某一方向移动一个时的花费的步数是一定的,那么,就可以先进

行一次预处理,预处理出对于目标棋子在上述条件下每次移动所需的步数。然后,预处理完成之后,我们会发现每次查询都会变成一个求最短路的问题,用Dijstra或SPFA的话,可以在时限范围内解决。(SPFA较好)

实现:

定义一个数组f[x][y][k][h],表示目标棋子在位置(x,y)且空格在目标棋子的k方向上的相邻格子时,目标棋子往h方向移动1格所需的步数,然后用状态[x][y][k]作为节点建图,用各个状态的关系连边,每次询问时重新定义一个源点跟终点,跑最短路就可以得出答案。

(预处理时跑n2次O(n2)的BFS就可以了)

[参考程序]

const  u:array[1..4] of integer=(-1,0,1,0);   //四种移法
      v:array[1..4] of integer=(0,1,0,-1);
      oo=100000000;
type node=record
      x,y,cs,l:longint;
end;
var ft:text;
    n,m,q,ii,i,i1,j1,j,l,w,x,y,x1,y1,x2,y2,x3,y3,es,ey,wei,tou,kx,ky,ans:longint;
    r:array[0..5000000] of node;
    aa,a,fb,fb2:array[0..31,0..31] of longint;
    ff,z,z2:array[0..31,0..31,1..4] of longint;
    f:array[0..31,0..31,1..4,1..4] of longint;
procedure bfs(x,y:longint);  //宽搜
var i,x1,y1:longint;
begin
  wei:=1;
  tou:=0;
  r[wei].x:=x; //r.x用来记录可以移动的横坐标
  r[wei].y:=y; //纵坐标
  r[wei].cs:=fb[x,y]; //几步可以移到
  while tou<wei do
   begin
    inc(tou);
    for i:=1 to 4 do //是否可以再向别的点移动
     begin
      x1:=r[tou].x+u[i];
      y1:=r[tou].y+v[i];
      if (a[x1,y1]=1)and(r[tou].cs+1<fb[x1,y1]) then //可以移到并且比之前的步数少
        begin
         inc(wei);
         r[wei].x:=x1;
         r[wei].y:=y1;
         r[wei].cs:=r[tou].cs+1;
         fb[x1,y1]:=r[wei].cs; //记录(等过程结束移到f四维数组里)
        end;
     end;
   end;
end;
begin
  readln(n,m,q);     //读入方阵
  for i:=1 to n do
    begin
    for j:=1 to m do
      read(a[i,j]);
    readln;
    end;
  aa:=a;
  for i:=1 to n do //初始化
   for j:=1 to m do
     begin
      fb2[i,j]:=oo;
      for l:=1 to 4 do
        begin
         z2[i,j,l]:=oo;
         for w:=1 to 4 do f[i,j,l,w]:=oo;
        end;
     end;
  for i:=1 to n do  //预处理
    for j:=1 to m do
     if a[i,j]=1 then  //如果该棋子可以移动
       for l:=1 to 4 do  //四个方向
         begin
          x:=i+u[l];
          y:=j+v[l];
          if (x>0)and(x<n+1)and(y>0)and(y<m+1)and(a[x,y]=1) then //假设四周有空格
            begin
             a[x,y]:=0;  //已被移动过,防止重复移动
             fb:=fb2;    //重置
             fb[i,j]:=1;  //空格移到这个位置
             bfs(i,j);
             for w:=1 to 4 do
               begin
                x1:=x+u[w];
                y1:=y+v[w];
                if (x1>0)and(x1<n+1)and(y1>0)and(y1<m+1)and(fb[x1,y1]<oo) then
                  begin
                  f[i,j,l,w]:=fb[x1,y1];  //记录表示目标棋子在位置(x,y)且空格在目标棋子的k方向上的相邻格子时,目标棋子往h方向移动1格所需的步数
                  end;
               end;
             a[x,y]:=1; //回溯
            end;
         end;
  for ii:=1 to q do
    begin
    read(kx,ky,x,y,es,ey);
    if (x=es)and(y=ey) then //如果初始位置与目标位置相同
      begin
       writeln(0);
       continue;
      end;
    fb:=fb2;  //
    a[x,y]:=0; //空格不能移到这个点
    fb[kx,ky]:=0; //空格移动0步到
    bfs(kx,ky);  //空格能到的地方
    wei:=0;
    z:=z2;  //重置
    fillchar(ff,sizeof(ff),0);
    for j:=1 to 4 do //目标棋子向四周移动
      begin
       x1:=x+u[j];
       y1:=y+v[j];
       if (x1>0)and(x1<n+1)and(y1>0)and(y1<m+1)and(fb[x1,y1]<oo) then //空格可以移到目标棋子所在格子
         begin  //记录
          inc(wei);
          r[wei].x:=x;
          r[wei].y:=y;
          r[wei].l:=j;  //表示方向
          z[x,y,j]:=fb[x1,y1]; //某位置向某方向最多可以移动几步
          ff[x,y,j]:=1;  //某位置向某方向可以移动
         end;
      end;
    tou:=0;
    while tou<wei do //SPFA
      begin
       inc(tou);
       for i:=1 to 4 do
        begin
         x2:=r[tou].x;
         y2:=r[tou].y;
         x1:=x2+u[r[tou].l]+u[i];
         y1:=y2+v[r[tou].l]+v[i];
         x3:=x2+u[r[tou].l];
         y3:=y2+v[r[tou].l];
        if (f[x2,y2,r[tou].l,i]<>oo)and(z[x3,y3,i]>z[x2,y2,r[tou].l]+f[x2,y2,r[tou].l,i]) then
begin
            z[x3,y3,i]:=z[x2,y2,r[tou].l]+f[x2,y2,r[tou].l,i];
            if ff[x3,y3,i]=0 then //记录
              begin
              ff[x3,y3,i]:=1;
              inc(wei);
              r[wei].x:=x3;
              r[wei].y:=y3;
              r[wei].l:=i;
              end;
           end;
         end;
       ff[r[tou].x,r[tou].y,r[tou].l]:=0;
      end;
    ans:=oo;
    for i:=1 to 4 do 查找
    if z[es,ey,i]<ans then ans:=z[es,ey,i];
if ans=oo then writeln(-1)
else writeln(ans);
    a[x,y]:=1; //回溯
  end;
end.

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-09 01:46:42

NOIP2013华容道——史上最强题解的相关文章

史上最强】网上所有的Axure元器件、UI、8.0安装包汉化包资源汇总

史上最强]网上所有的Axure元器件.UI.8.0安装包汉化包资源汇总        目前产品经理工具中应该最火的就是axure了,简直就是人人必备.确实,在实现一些复杂的交互上,axure很管用,但是也有缺点,就是元器件不够多,很多要自己画,不美观.今天,8kvv就给大家整理了现有axure的元器件.Axure8.0.axure汉化包.苹果iOSUI及安卓5.0安卓6.0UI.很全啦! 大家慢慢欣赏哦! 列举下为大家整理的网上所有的Axure的实用资源(下载地址在最后),包括: 1.Axure

【史上最强JavaSE笔记】之数组篇

各位程序猿,各位攻城狮,各位蜥蜴鸥以及各位棕鲸鲤们~~大家好,我是潘师傅,欢迎大家收看由我为你们带来的[史上最强JavaSE笔记]系列,其实也可以叫[嘻哈JavaSE笔记]的,第一次在博客园发帖,想想还真是有点小激动呢,各位求支持呀,哈哈,那么回归正题,我把自己之前学习积累的笔记拿出来跟大家分享一下,方便大家更好的理解和复习,希望能够对大家有所帮助哈,这次发的是JavaSE方面数组篇的,内容不一定全面哦,欢迎大家前来留言交流哈,不足的地方还望大家多多指出和指导哈~(由于首次发文章,布局可能比较乱

史上最强实名制来袭!究竟切中了谁的要害?

对常在互联网上蹦跶的你,现在只想说三个字:实名制!近日,bilibili(B站)发布公告称,"应国家相关政策规定要求,从7月5日开始,UP主(视频创作者或上传者)上传视频内容(包括新增.编辑.换源等)需通过实名验证,方可编辑视频稿件".而这,可以看做是史上最强实名制的一部分. 事实上,近段时间以来,实名制是一直是网上热议的争议性话题之一.是否需要实名制.是否对部分用户的隐私权构成威胁.是否影响言论自由及互联网开放的本质精神.实名制究竟有多大的威慑力--史上最强实名制的全面来袭,究竟切中

史上最强型人养成秘籍: 90 天肥仔变型男实录

史上最强型人养成秘籍: 90 天肥仔变型男实录[12P] 这是一篇最近很火的帖子.主人公B.K ,是一个从来没有看见过自己腹肌的三十三岁中年普通男人,就是因为青春易逝的危机感,让他下定决心给自己一个交代!于是用了九十天,他做到了!减脂和塑身计划从2014年3 月15日开始到6月25日结束,从一个非典型性胖子.微胖界翘楚.土圆肥代表,到八块腹肌霸气外露,仅仅90天. 前几天在机场,遇见一个三四个月没见的小姐妹,在她面前半天没认出我.这样的情况,近期已经第三次了.因为这个原因,我不得已又去拍了新的证

史上最强算法论战:请不要嘻哈,这是哈希[下]

史上最强算法论战:请不要嘻哈,这是哈希[下] 欢迎个人转发朋友圈,机构及媒体转载需在开篇声明,转自微信公号“知象科技” 论战主角之一龙博:知象科技CEO,欲了解龙博及知象科技,请点击文末“阅读原文”. 这是“美丽互联”微信群里的一次算法论战,感谢书记员硅谷寒(梁寒)精彩的说书般的整理. 书接上文 一夜过去了…孤独虎精神抖擞的回来了! [书记员注:上集说到独孤虎被龙博两次判零分,已经到了精神分裂的边缘.于是他决定回家休养生息,以图再战.果不其然,第二天,独孤虎首先跳出来,带来了他的第四种方案.我们

翻翻git之---史上最强的图片选择器 GalleryFinal(顺带附下麦麦,当当的近照)

转载请注明出处:王亟亟的大牛之路 技术内容在P2,P1是废话可以跳过 P1:(开胃菜) 最近手头上工作的事差不多告一段落了,可以把更多的精力花在学习上了,还是会继续翻git这部分的文章(搬运工),然后准备整整一些之前没接触过的知识点(具体学什么没想好,等会看看去) 先上一下家里宝贝的近照 P2:(正菜) 今天上的是一个自称是"史上最强的图片选择器" GalleryFinal 话不多说先看看效果 作者几乎实现了我们平时所需的"皂片"选择器的所有功能,还带有一定的编辑和

喜欢,就要说出来,别等错失后才觉醒!史上最强告白!

喜欢,就要说出来,别等错失后才觉醒!史上最强告白!! 2016-08-06 亚谷科技 下辈子也要找到你 孙露 - 孙情流露 人一生会错过很多东西, 回得了过去,回不了当初. 关于爱情 喜欢 就要大声的说出来, 别再去等一个人.或者等一个故事. <偶像版> <太阳的后裔>第一集里男主就喜欢上了女主. -- “和我一起看电影吧?快回答,没时间了,好还是不好?” -- “好!” -- “那就这样说定了!” 喜欢就别矫情   <剧情版> “不好意思,刚认识就喜欢你!” 无论结果

【插件】史上最强编辑器通用ctags插件OpenCTags使用指南v1.2--开发者必备

Changes Log: v1.2.0 2011-12-4 支持Java编写的可以设置用户配置的编辑工具 增加当前文件类查找Tags功能 增加设置当前目录参数 完善多种主流轻量级编辑器的配置 v1.1.0 2011-11-26 完善提示窗口的显示样式 编辑器配置使用Json格式配置文件,方便定制到自己喜欢的编辑器,主流编辑器一网打尽 v1.0.4 2011-11-21 支持提示窗口拖动,按住鼠标右键,即可拖拖拖[上一版本为鼠标左键] 增加回车键功能,按下可以会自动打开对应的文件并定位到对应的位置

豆瓣看到一个史上最强最犀利骂人帖

豆瓣看到一个史上最强最犀利骂人帖 http://beijing.edeng.cn/xinxi/179414813.htmlhttp://beijing.edeng.cn/xinxi/179414852.htmlhttp://beijing.edeng.cn/xinxi/179414847.htmlhttp://beijing.edeng.cn/xinxi/179414862.htmlhttp://beijing.edeng.cn/xinxi/179414872.htmlhttp://beijin