luogu P1979 [NOIP2013] 华容道
这道题中,棋子的移动是要移动到空格上去,所以空格要在棋子旁边才能移动棋子;而棋子移动的方向由空格决定
所以我们可以记三维状态\(di_{i,j,k}\),表示状态为棋子在\((i,j)\),空格在棋子\(k\)方向(顺时针编号0到3)上的最短距离
要\(bfs\)预处理\(mv_{i,j,k,l}\),表示不动\((i,j)\),把空格从\(k\)方向移到\(l\)方向的最短距离.转移时枚举棋子要走的方向\(l\),然后要把空格移到棋子\(l\)方向,再让棋子走上去,注意走完后空格会在棋子的\((l+2)\ mod\ 4\)方向,所以\(di_{i1,j1,(l+2)\ mod\ 4}=di_{i,j,k}+mv_{i,j,k,l}+1\)
转移的话推荐用\(spfa\)(我\(spfa\)还活着,,,_ (: 」∠) _)等最短路算法
还有处理初始状态时,要把空格先移动到棋子对应方向上
#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define inf 1061109567
using namespace std;
const int N=40,M=20000+10;
il LL rd()
{
    re LL x=0,w=1;re char ch=0;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int to[M<<1],nt[M<<1],w[M<<1],hd[M],tot=1;
il void add(int x,int y,int z){++tot,to[tot]=y,nt[tot]=hd[x],w[tot]=z,hd[x]=tot;}
int mm[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int n,m,q,a[N][N],nxt[4]={2,3,0,1}; //nxt[i]=(i+2)%4
int mv[N][N][4][4];
int id[N][N][4],di[M];
int vis[N][N],ti;
bool v[M];
struct nnn
{
  int sx,sy,f,d;
};
int gdis(int x,int y,int tx,int ty,int d)
{
  vis[x][y]=ti;
  queue<nnn> q;
  q.push((nnn){x,y,0,0});
  while(!q.empty())
    {
      x=q.front().sx,y=q.front().sy,d=q.front().d;
      q.pop();
      if(x==tx&&y==ty) return d;
      for(int j=0;j<4;j++)
        {
          int xx=x+mm[j][0],yy=y+mm[j][1];
          if(vis[xx][yy]<ti&&a[xx][yy]) vis[xx][yy]=ti,q.push((nnn){xx,yy,0,d+1});
        }
    }
  return inf;
}
int main()
{
  n=rd(),m=rd(),q=rd();
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
      for(int k=0;k<4;k++)
        id[i][j][k]=(((i-1)*m+j)<<2)+k;
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
      a[i][j]=rd();
  memset(mv,63,sizeof(mv));
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
      {
        if(!a[i][j]) continue;
        for(int k=0;k<4;k++)
          {
            if(!a[i+mm[k][0]][j+mm[k][1]]) continue;
            for(int l=0;l<4;l++)
              {
                if(!a[i+mm[l][0]][j+mm[l][1]]) continue;
                if(k==l) {mv[i][j][k][l]=0;continue;}
                a[i][j]=0,++ti,mv[i][j][k][l]=gdis(i+mm[k][0],j+mm[k][1],i+mm[l][0],j+mm[l][1],0),a[i][j]=1;
              }
          }
      }
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
      for(int k=0;k<4;k++)
        for(int l=0;l<4;l++)
          add(id[i][j][k],id[i+mm[l][0]][j+mm[l][1]][nxt[l]],mv[i][j][k][l]+1);
  while(q--)
    {
      int ex=rd(),ey=rd(),sx=rd(),sy=rd(),tx=rd(),ty=rd();
      if(sx==tx&&sy==ty) {puts("0");continue;}
      memset(di,63,sizeof(di));
      queue<int> q;
      a[sx][sy]=0;
      for(int j=0;j<4;j++) ++ti,di[id[sx][sy][j]]=gdis(ex,ey,sx+mm[j][0],sy+mm[j][1],0),q.push(id[sx][sy][j]);
      a[sx][sy]=1;
      while(!q.empty())
        {
          int x=q.front();
          q.pop();
          for(int i=hd[x];i;i=nt[i])
            {
              int y=to[i];
              if(di[y]>di[x]+w[i])
                {
                  di[y]=di[x]+w[i];
                  if(!v[y]) q.push(y);
                  v[y]=true;
                }
            }
          v[x]=false;
        }
      int ans=min(min(di[id[tx][ty][0]],di[id[tx][ty][1]]),min(di[id[tx][ty][2]],di[id[tx][ty][3]]));
      printf("%d\n",ans<inf?ans:-1);
    }
  return 0;
}
luogu P1979 [NOIP2013] 华容道的更多相关文章
- Luogu 1979 [NOIP2013] 华容道
		要优先安排历年NOIP题 考虑到要移动,肯定要先把空的格子移动到起点旁边,所以我们对于每一个询问都先bfs一次求出把空格移到起点的四个位置的最短路,而且要保证不能移动起点的方块. 只有空的格子在一个格 ... 
- Luogu 1970 NOIP2013 花匠 (贪心)
		Luogu 1970 NOIP2013 花匠 (贪心) Description 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使 ... 
- [Luogu 1967] NOIP2013 货车运输
		[Luogu 1967] NOIP2013 货车运输 一年多前令我十分头大的老题终于可以随手切掉了- 然而我这码风又变毒瘤了,我也很绝望. 看着一年前不带类不加空格不空行的清纯码风啊,时光也好像回去了 ... 
- LOJ2613 NOIP2013 华容道 【最短路】*
		LOJ2613 NOIP2013 华容道 LINK 这是个好题,具体题意比较麻烦可以直接看LINK中的链接 然后考虑我们可能的移动方式 首先我们需要把白块移动到需要移动块S的附近(附近四格) 然后我们 ... 
- [NOIP2013]华容道 题解(搜索)
		[NOIP2013]华容道 [题目描述] 这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街.考后想想也是,数据这么小一定有他的道理. 首先由于是最小步数,所以BFS没跑了.那么我们大可把这 ... 
- [NOIP2013]华容道 题解
		[NOIP2013]华容道 首先是一种比较显然的做法. 整个棋盘,除了起点,终点和空格,其他的方块是等价的. 对于终点,它始终不会变化,如果搜到终点结束搜索即可,所以我们不需要考虑终点. 所以需要考虑 ... 
- Luogu P1979 华容道(bfs+最短路)
		P1979 华容道 题意 题目描述 小B最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成, 最少需要多少时间. ... 
- 洛谷P1979 [NOIP2013提高组Day2T3]华容道
		P1979 华容道 题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少 ... 
- luogu P1979 华容道
		solution 被假hash可了半天....sadQAQ code // luogu-judger-enable-o2 #include<queue> #include<cstdi ... 
随机推荐
- js數字
			js數字只有一種類型:不是類型語言. js的數字可以使用科學計數法或者不使用科學計數法: js都是64位的, 如果是整數,(不使用科學計數法或者是小數點)最大15位的: 如果是浮點數,最大17位的,浮 ... 
- c++ 为自定义类添加stl遍历器风格的遍历方式
			为仿照stl的遍历风格,实现对自定义类型的遍历. 1. 需要遍历的基础结构: struct ConnectionPtr { int id_; int port_; string addr_; //st ... 
- Luogu5055 【模板】可持久化文艺平衡树(fhq-treap)
			注意下传标记时也需要新建节点.空间开的尽量大. #include<iostream> #include<cstdio> #include<cmath> #inclu ... 
- BZOJ4200 NOI2015小园丁与老司机(动态规划+上下界网络流)
			一看上去就是一个二合一的题.那么先解决第一部分求最优路线(及所有可能在最优路线上的线段). 由于不能往下走,可以以y坐标作为阶段.对于y坐标不同的点,我们将可以直接到达的两点连边,显然这样的边的个数是 ... 
- 自学Python6.2-类、模块、包
			自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ... 
- [luogu1373]小a和uim之大逃离【动态规划】
			传送门:https://www.luogu.org/problemnew/show/P1373 定义状态是:\(f[i][j][h][0..1]\)表示在\([i,j]\)两个人相差为h,让某一个人走 ... 
- CF528D Fuzzy Search  【NTT】
			题目链接 CF528D 题解 可以预处理出\(S\)每个位置能匹配哪些字符 对每种字符 构造两个序列 如果\(S[i]\)可以匹配该字符,则该位置为\(0\),否则为\(1\) 如果\(T[i]\)可 ... 
- rsync同步官方zabbix仓库搭建本地yum源
			1.同步资源 # rsync -vrt rsync://repo.zabbix.com/mirror/zabbix/3.4/rhel/7/x86_64/ /home/mirrors/zabbix/3. ... 
- Python基础-简介一
			一.Python介绍 1. Python的应用领域及流行程度 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间, ... 
- react与react-router
			路由在单页应用极其常见,不论是angularjs项目还是react项目,都有路由. 在react项目中使用路由,我们当然是全局安装react-router. 第一步: 第二步:创建几个要跳转到的页面 ... 
