题目:https://www.luogu.org/problemnew/show/P1979

真是一道好题...

首先考虑暴力做法,应该是设 f[i][j][x][y] 记录指定棋子和空格的位置,然后 bfs 转移;

然后发现,这些状态中有很多无用的,换句话说,就是仅当空格在指定棋子旁边时才有用,能带来棋子的移动;

所以不妨只记录 f[i][j][k] ,k 表示空格在指定棋子 (i,j) 的哪个方向;

两种转移:1.指定棋子不动,空格从它的一边移动到另一边;

2.指定棋子和空格交换位置;

所以给可以相互转移的状态之间连边,SPFA 跑最短路;

初始状态空格不一定在指定棋子旁边,所以专门 bfs 一下,得到空格在指定棋子旁边的状态;

由于空格可以在指定棋子的四个方向,所以要跑多源最短路;

连边时给每个状态直接记一个 id 比较方便;

调了半天终于65分,加个特判:起点就是终点时输出0,就 A 了~

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int const xn=,xm=,inf=1e9;
int n,m,Q,f[xn][xn][][],id[xn][xn][],dx[]={-,,,},dy[]={,,-,};//0,1,2,3 -> 上下左右
int hd[xm],ct,to[xm<<],nxt[xm<<],dis[xm<<],w[xm<<];
bool v[xn][xn],vis[xn][xn],vis2[xm];
struct N{int x,y,d;};
queue<N>q;
queue<int>q2;
void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;}
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return f?ret:-ret;
}
bool ck(int x,int y){return x>=&&x<=n&&y>=&&y<=m&&!v[x][y];}
int bfs(int x,int y,int p1,int p2)
{
while(q.size())q.pop();
memset(vis,,sizeof vis);
int sx=x+dx[p1],sy=y+dy[p1];
int xx=x+dx[p2],yy=y+dy[p2];
if(!ck(sx,sy)||!ck(xx,yy))return inf;
q.push((N){sx,sy,});
vis[sx][sy]=; vis[x][y]=;//!!
while(q.size())
{
int tx=q.front().x,ty=q.front().y,d=q.front().d; q.pop();
for(int i=,nx,ny;i<;i++)
{
nx=tx+dx[i]; ny=ty+dy[i];
if(!ck(nx,ny)||vis[nx][ny])continue;
if(nx==xx&&ny==yy)return d+;
else q.push((N){nx,ny,d+}),vis[nx][ny]=;
}
}
return inf;
}
void init()
{
int cnt=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
for(int k=;k<;k++)
{
id[i][j][k]=++cnt;
if(v[i][j])continue;
for(int l=k+;l<;l++)
f[i][j][k][l]=bfs(i,j,k,l);
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
for(int k=;k<;k++)
{
int x=i+dx[k],y=j+dy[k],a=id[i][j][k],b;
if(!ck(x,y))continue;
// for(int l=0;l<4;l++) //i,j表示指定棋子位置,不可有共用空格的点之间连0的边!(否则没算上指定棋子的移动代价)
// {
// int nx=x+dx[l],ny=y+dy[l];
// if(!ck(nx,ny)||(nx==i&&ny==j))continue;
// b=id[nx][ny][l^1];
// add(a,b,0); add(b,a,0);
// }
if(v[i][j])continue;
for(int l=k+;l<;l++)
{
int nx=i+dx[l],ny=j+dy[l];
if(!ck(nx,ny)||f[i][j][k][l]==inf)continue;
b=id[i][j][l];
add(a,b,f[i][j][k][l]); add(b,a,f[i][j][k][l]);
}
b=id[x][y][k^];
add(a,b,); add(b,a,);
}
}
int is(int x,int y,int xx,int yy)
{
for(int k=;k<;k++)
if(x+dx[k]==xx&&y+dy[k]==yy)return k;
return -;
}
int work(int ex,int ey,int sx,int sy,int tx,int ty)
{
while(q.size())q.pop(); while(q2.size())q2.pop();
memset(vis,,sizeof vis);
memset(vis2,,sizeof vis2);
memset(dis,0x3f,sizeof dis);
q.push((N){ex,ey,}); vis[ex][ey]=;
vis[sx][sy]=;//!!
int k=is(sx,sy,ex,ey),bh;
if(k!=-)q2.push(bh=id[sx][sy][k]),vis2[bh]=,dis[bh]=;
while(q.size())
{
int x=q.front().x,y=q.front().y,d=q.front().d; q.pop();
for(int i=;i<;i++)
{
int tx=x+dx[i],ty=y+dy[i];
if(!ck(tx,ty)||vis[tx][ty])continue;
int k=is(sx,sy,tx,ty); int bh;
if(k!=-)q2.push(bh=id[sx][sy][k]),vis2[bh]=,dis[bh]=d+;
q.push((N){tx,ty,d+});
vis[tx][ty]=;
}
}
while(q2.size())
{
int x=q2.front(); q2.pop(); vis2[x]=;
for(int i=hd[x],u;i;i=nxt[i])
{
u=to[i];
if(dis[u=to[i]]>dis[x]+w[i])
{
dis[u]=dis[x]+w[i];
if(!vis2[u])q2.push(u),vis2[u]=;
}
}
}
int ans=inf;
for(int k=;k<;k++)ans=min(ans,dis[id[tx][ty][k]]);
if(ans==inf)return -;
return ans;
}
int main()
{
n=rd(); m=rd(); Q=rd();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)v[i][j]=!rd();
init();
for(int i=,ex,ey,sx,sy,tx,ty;i<=Q;i++)
{
ex=rd(); ey=rd(); sx=rd(); sy=rd(); tx=rd(); ty=rd();
if(sx==tx&&sy==ty)printf("0\n");//!!!
else printf("%d\n",work(ex,ey,sx,sy,tx,ty));
}
return ;
}

洛谷 P1979 [ NOIP 2013 ] 华容道 —— bfs + 最短路的更多相关文章

  1. 洛谷 P3953 [ NOIP 2017 ] 逛公园 —— 最短路DP

    题目:https://www.luogu.org/problemnew/show/P3953 主要是看题解...还是觉得好难想啊... dfs DP,剩余容量的损耗是边权减去两点最短路差值...表示对 ...

  2. Luogu 1979 NOIP 2013 华容道(搜索,最短路径)

    Luogu 1979 NOIP 2013 华容道(搜索,最短路径) Description 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面 ...

  3. 洛谷模拟NOIP考试反思

    洛谷模拟NOIP考试反思 想法 考了这么简单的试qwq然而依然emmmmmm成绩不好 虽然本次难度应该是大于正常PJ难度的但还是很不理想,离预估分数差很多qwq 于是就有了本反思嘤嘤嘤 比赛链接 原比 ...

  4. 【noip】跟着洛谷刷noip题2

    noip好难呀. 上一个感觉有点长了,重开一个. 36.Vigenère 密码 粘个Openjudge上的代码 #include<cstdio> #include<iostream& ...

  5. 洛谷 P3951 NOIP 2017 小凯的疑惑

    洛谷 P3951 NOIP 2017 小凯的疑惑 题目描述 小凯手中有两种面值的金币,两种面值均为正整数且彼此互素.每种金币小凯都有 无数个.在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付 ...

  6. 洛谷 P1979 华容道 解题报告

    P1979 华容道 题目描述 小\(B\)最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时 ...

  7. Luogu P1979 华容道(bfs+最短路)

    P1979 华容道 题意 题目描述 小B最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成, 最少需要多少时间. ...

  8. 【noip】跟着洛谷刷noip题

    传送门 1.铺地毯 d1t1 模拟 //Twenty #include<cstdio> #include<cstdlib> #include<iostream> # ...

  9. 洛谷 P5304 [GXOI/GZOI2019]旅行者(最短路)

    洛谷:传送门 bzoj:传送门 参考资料: [1]:https://xht37.blog.luogu.org/p5304-gxoigzoi2019-lv-xing-zhe [2]:http://www ...

随机推荐

  1. cookie和session的区别及session的生命周期

    这些都是基础知识,不过有必要做深入了解.先简单介绍一下. 二者的定义: 当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cookie 会帮你在网站上所打的文字或是一些选择,都纪录 ...

  2. xphrof性能分析线上部署实践

    说明 将xhprof部署在线上环境,在特定情况下进行性能分析,方便快捷的排查线上性能问题. 通过参数指定及添加代码行触发进入性能分析,并将结果保存入MongoDB. 因为xhprof对性能的影响,只部 ...

  3. c++基础_矩阵乘法

    #include <iostream> using namespace std; int main(){ int a,b; cin>>a>>b; long c[a] ...

  4. 【转】Comet:基于 HTTP 长连接的“服务器推”技术

    原文链接:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 很多应用譬如监控.即时通信.即时报价系统都需要将后台发生的变化实时传送到客户端而无 ...

  5. 解决idea创建ssm项目找不到mybatis的mapper的xml文件问题

    http://blog.csdn.net/v19freedom/article/details/69855302 后来上网搜了下,别人给出的答复 idea在build工程的时候 遇到maven项目 使 ...

  6. 【BZOJ3110】K大数查询(权值线段树套线段树+标记永久化,整体二分)

    题意:有N个位置,M个操作.操作有两种,每次操作 如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是 ...

  7. 【BZOJ3669】魔法森林(LCT)

    题意:有一张无向图,每条边有两个权值.求选取一些边使1和n连通,且max(a[i])+max(b[i])最小 2<=n<=50,000 0<=m<=100,000 1<= ...

  8. mysql性能调优——Query优化

    上节谈了关于mysql锁定机制的优化方案,下面来谈一下Query优化——Mysql Query Optimizer 当Mysql Query Optimizer接受到从Query Parser过来的Q ...

  9. JSP的Cookie处理

    以下内容引用自http://wiki.jikexueyuan.com/project/jsp/Cookies-handling.html: Cookies是存储在客户端计算机的文本文件,保存各种跟踪目 ...

  10. PyMySQL - Python3 MySQL数据库连接 - 基本操作

    一.Python连接MySQL数据库   1.导入模块 #导入模块 import pymysql   2.打开数据库连接 #打开数据库连接 #注意:这里已经假定存在数据库testdb,db指定了连接的 ...