【NOIP2013】华容道
看别人的代码然后被坑了一下午+一晚上,睡一觉第二天醒悟过来打表过了
果然打表才是正确的调试方法,跟踪什么的去屎(╯‵□′)╯︵┻━┻
原题:
小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次。于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间。
小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的:
1. 在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1 个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的;
2. 有些棋子是固定的,有些棋子则是可以移动的;
3. 任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。
游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。
给定一个棋盘,游戏可以玩 q 次,当然,每次棋盘上固定的格子是不会变的,但是棋盘上空白的格子的初始位置、指定的可移动的棋子的初始位置和目标位置却可能不同。第 i 次玩的时候,空白的格子在第 EX[i] 行第 EY[i] 列,指定的可移动棋子的初始位置为第 SX[i] 行第 SY[i] 列,目标位置为第 TX[i] 行第 TY[i] 列。
假设小 B 每秒钟能进行一次移动棋子的操作,而其他操作的时间都可以忽略不计。请
你告诉小 B 每一次游戏所需要的最少时间,或者告诉他不可能完成游戏。
1 ≤ n, m ≤ 30,q ≤ 500。
这题暴力分很实惠,很容易写出一个bfs能拿到60-70
想要A掉怎么办呐
正解就要魔性p♂l♀a♂y了
用一个状态b[i][j][k][h]表示第i行第j列的格子,空格在k方向,这个格子要移动到h方向需要的最小步数
这个步数怎么求呐
可以用一个bfs,求出空格从k方向到h方向需要的步数,然后需要移动的格子和h方向的空格交换即可,可以证明这样做是最优的(逃
然后一个三维的点c[i][j][k]表示第i行第j列的格子,空格在k方向,上面用bfs求出步数↑后就可以把c[i][j][k]与c[i+k方向上x的变化量][j+k方向上y的变化量][h的反方向]连上权值为步数的边
因为求出步数的方法是先把空格移到h方向,在把格子和空格交换↑,所以边的汇点的方向是h的反方向
然后每次询问的时候,可以直接套用上面的bfs↑求出把空白格移动到要移动的方格附近需要的步数,四个方向都搞一下,建一个源点s,把s与c[i][j][k]连上权值为步数的边
然后再建一个汇点t,把t和c[目标节点x][目标节点y][四个方向]连上权值为0的边
然后就可以开心地搞最短路辣
需要注意的的方:
最好判断一下要移动的格子和目标格子是一个东西以及要移动的格子或目标格子不合法的情况
连边的时候需要注意什么时候坐标要加上方向,什么时候坐标是原格子
小技巧:
可以用一个计数,在输入数据的时候给每个c[i][j][k]都标上号,连边的时候就很方便
把x和y的变化量分别设成{1,-1,0,0},{0,0,1,-1},这样直接用k^1就可以快速取到反向边
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int oo=;
int fx[]={,-,,},fy[]={,,,-};
struct ddd{int next,y,value;}e[];int LINK[],ltop=;
inline void insert(int x,int y,int z){e[++ltop].next=LINK[x];LINK[x]=ltop;e[ltop].y=y;e[ltop].value=z;}
int m,n,q,a[][];
int hash[][][],hash_cnt=;
int dui[],tou=;
int bf[][];
int s,t;
int sf[];
bool visited[];
int bfs(int sx,int sy,int tx,int ty){
memset(bf,,sizeof(bf));
dui[tou=]=(sx-)*n+sy-; bf[sx][sy]=;
for(int k=;k<=tou;k++){
int x=dui[k]/n+,y=dui[k]%n+;
for(int i=;i<;i++)if(a[x+fx[i]][y+fy[i]] && bf[x+fx[i]][y+fy[i]]>bf[x][y]+){
bf[x+fx[i]][y+fy[i]]=bf[x][y]+;
//if(x+fx[i]==tx && y+fy[i]==ty) return bf[tx][ty];
dui[++tou]=(x+fx[i]-)*n+y+fy[i]-;
}
}
return bf[tx][ty];
}
int spfa(){
memset(sf,,sizeof(sf));
memset(visited,,sizeof(visited));
dui[tou=]=s; sf[s]=;
for(int k=;k<=tou;k++){
visited[dui[k]]=false;
for(int i=LINK[dui[k]];i;i=e[i].next)
if(sf[e[i].y]>sf[dui[k]]+e[i].value){
sf[e[i].y]=sf[dui[k]]+e[i].value;
if(!visited[e[i].y]) dui[++tou]=e[i].y,visited[e[i].y]=true;
}
}
return (sf[t]<oo) ? sf[t] : -;
}
int main(){//freopen("ddd.in","r",stdin);
cin>>m>>n>>q;
for(int i=;i<=m;i++) for(int j=;j<=n;j++){
scanf("%d",&a[i][j]);
for(int k=;k<;k++) hash[i][j][k]=++hash_cnt;
}
for(int i=;i<=m;i++)
for(int j=;j<=n;j++)if(a[i][j])
for(int k=;k<;k++)if(a[i+fx[k]][j+fy[k]]){
insert(hash[i][j][k],hash[i+fx[k]][j+fy[k]][k^],);
//cout<<i<<" "<<j<<" "<<k<<" "<<i+fx[k]<<" "<<j+fy[k]<<" "<<(k^1)<<" "<<1<<endl;
for(int q=;q<;q++)if(q!=k && a[i+fx[q]][j+fy[q]]){
a[i][j]=;
int bu=bfs(i+fx[k],j+fy[k],i+fx[q],j+fy[q])+;
if(bu<oo){ insert(hash[i][j][k],hash[i+fx[q]][j+fy[q]][q^],bu); /*cout<<i<<" "<<j<<" "<<k<<" "<<i+fx[q]<<" "<<j+fy[q]<<" "<<(q^1)<<" "<<bu<<endl;*/}
a[i][j]=;
}
}
int sx,sy,tx,ty,kx,ky;
while(q --> ){//趋向于
scanf("%d%d%d%d%d%d",&kx,&ky,&sx,&sy,&tx,&ty);
if(sx==tx && sy==ty){ printf("0\n"); continue;}
if(!a[sx][sy] || !a[tx][ty]){ printf("-1\n"); continue;}
s=++hash_cnt;t=++hash_cnt;
a[sx][sy]=;
for(int k=;k<;k++)if(a[sx+fx[k]][sy+fy[k]]){
int bu=bfs(kx,ky,sx+fx[k],sy+fy[k]);
if(bu<oo) insert(s,hash[sx][sy][k],bu);
}
a[sx][sy]=;
for(int k=;k<;k++)if(a[tx+fx[k]][ty+fy[k]])
insert(hash[tx][ty][k],t,);
printf("%d ",spfa());
}
return ;
}
【NOIP2013】华容道的更多相关文章
- LOJ2613 NOIP2013 华容道 【最短路】*
LOJ2613 NOIP2013 华容道 LINK 这是个好题,具体题意比较麻烦可以直接看LINK中的链接 然后考虑我们可能的移动方式 首先我们需要把白块移动到需要移动块S的附近(附近四格) 然后我们 ...
- [NOIP2013]华容道 题解(搜索)
[NOIP2013]华容道 [题目描述] 这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街.考后想想也是,数据这么小一定有他的道理. 首先由于是最小步数,所以BFS没跑了.那么我们大可把这 ...
- [NOIP2013]华容道 题解
[NOIP2013]华容道 首先是一种比较显然的做法. 整个棋盘,除了起点,终点和空格,其他的方块是等价的. 对于终点,它始终不会变化,如果搜到终点结束搜索即可,所以我们不需要考虑终点. 所以需要考虑 ...
- [NOIP2013]华容道
1.题面 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间.小 B 玩的华容道与经典 ...
- noip2013华容道
题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间. 小 ...
- NOIP2013 华容道 (棋盘建图+spfa最短路)
#include <cstdio> #include <algorithm> #include <cstring> #include <queue> # ...
- NOIP2013华容道 大爆搜
预处理出每个点周围四个点互相到达的最短路,再在整个图上跑SPFA,要记录路径 #include<cstdio> #include<cstring> #include<io ...
- NOIP2013华容道(BFS+乱搞)
n<=30 * m<=30 的地图上,0表示墙壁,1表示可以放箱子的空地.q<=500次询问,每次问:当空地上唯一没有放箱子的空格子在(ex,ey)时,把位于(sx,sy)的箱子移动 ...
- luogu P1979 [NOIP2013] 华容道
传送门 这道题中,棋子的移动是要移动到空格上去,所以空格要在棋子旁边才能移动棋子;而棋子移动的方向由空格决定 所以我们可以记三维状态\(di_{i,j,k}\),表示状态为棋子在\((i,j)\),空 ...
- [Luogu1979][NOIP2013]华容道(BFS+SPFA)
考虑从起点到终点的过程,一定是先将空格子移到指定格子旁边,和指定格子交换,再移到下一个指定格子要到的地方,再交换,如此反复. 于是问题分为两个部分: 1.给定两个曼哈顿距离为2的格子求最短路,BFS即 ...
随机推荐
- 100个iOS开发/设计面试题汇总
常见问题 你昨天/这周学习了什么? 你为什么热衷于软件开发? 你对哪一种控制系统比较熟悉? 是否参与过GitHub项目? 是否参与过GitHub或其他同类型网站的iOS开源项目? 请描述一下你的iOS ...
- 微软发布Windows Phone 8.1 Update 和中文版Cortana“小娜”
Windows Phone 8.1 尚在推送进程中,它的第一个 GDR 更新就发布了.今天微软正式发布 Windows Phone 8.1 Update 和中文版 Cortana ——“小娜”. Wi ...
- Yslow&PageSpeed– 诊断各种缓慢症状
Google的PageSpeed和yahoo的yslow是各位不可少的前端工具(同样也都是firebug的插件,安装了firebug之后才可以拥有她们),当各位无法用三寸不烂之舌收拾产品和各种大佬的时 ...
- iOS 网络判定
由于流量精灵需要在 蜂窝数据或者3G 环境下进行流量监控因此需要判定3G 环境 将 SystemConfiguration.framework 添加进工程: 引入头文件 #import <Sys ...
- 学习LCMapString和LCMapStringEx
LCMapStringEx: http://msdn.microsoft.com/en-us/library/windows/desktop/dd318702(v=vs.85).aspx For a ...
- Android USB Connections Explained: MTP, PTP, and USB Mass Storage
Android USB Connections Explained: MTP, PTP, and USB Mass Storage Older Android devices support USB ...
- 程序员最爱 Mac、JS 是最热门技术
概况: 今年,有超过5万名开发者向我们分享了他们是谁,做什么工作,以及他们的成果.通过本文,你将看到有史以来最为全面的一次开发者情况调查的结果. 每8秒钟,就会有一位开发者在Stack Overflo ...
- hdu 2061
PS: 以为找个简单来恢复信心..结果碰到那么傻逼的题目... 题意:给出学分和成绩,算GPA...关键是注意换行....它要求的换行我觉得超级奇怪...除了第一个正常,其他的输入完之后先一个换行. ...
- linux下的定时任务
cronb命令 在Linux中,周期执行的任务一般由cron这个守护进程来处理.ps -ef | grep cron.cron读取一个或多个配置文件,这些配置文件中包含了命令行及其调用时间. cron ...
- Cisco ASA端口映射
Cisco ASA 端口映射设置 1.使用ASDM进入到配置页面,点开NAT Rules,然后新增Network Object,NAT选项如下图所示设定. 下图设定外网IP映射到内网IP地址192.1 ...