题目: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. [bzoj3531][Sdoi2014][旅行] (主席树+树链剖分)

    Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. ...

  2. C语言基础--自加自减

    有如下代码: unsigned int temp1,temp2, i=5,j=5; temp1=i++; temp2=++j; 结果是 temp1=5,temp2=6: i=6,j=6: 版权声明:本 ...

  3. Leetcode 139.单词拆分

    单词拆分 给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词. 说明: 拆分时可以重复使用字典中的单词. 你可以假设字典 ...

  4. hihoCoder#1042 跑马圈地

    原题地址 经网友jokeren提醒,后面给出的代码虽然可以AC原题,但存在bug,主要是在矩形覆盖情况的判断上处理的不够完全. 看似挺复杂的,但是仔细分析一下可以化简: 首先,不用枚举周长,因为更长的 ...

  5. 微信开放平台PC端扫码登录功能个人总结

    最近公司给我安排一个微信登录的功能,需求是这样的: 1.登录授权 点击二维码图标后,登录界面切换为如下样式(二维码),微信扫描二维码并授权,即可成功登录:    若当前账号未绑定微信账号,扫描后提示“ ...

  6. 详解SpringBoot 添加对JSP的支持(附常见坑点)

    序言: SpringBoot默认不支持JSP,如果想在项目中使用,需要进行相关初始化工作.为了方便大家更好的开发,本案例可直接作为JSP开发的脚手架工程 SpringBoot+War+JSP . 常见 ...

  7. codevs3164 质因数分解

    题目描述 Description (多数据)给出t个数,求出它的质因子个数. 数据没坑,难度降低. 输入描述 Input Description 第一行 t 之后t行 数据 输出描述 Output D ...

  8. 新vim配置文件

    "******************************************************特殊设置************************************ ...

  9. Linux下汇编语言学习笔记24 ---

    这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...

  10. SPFA 算法

    百度百科: http://baike.baidu.com/link?url=O0QvxbOY8SVBjrIl6nF6EvMHSslgcEIxfXSoty5SbkA7QjbWZjTWARzwTQsKKb ...