华容道

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 34  Solved: 14
[Submit][Status][Web Board]

Description

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

小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的:

1.       在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1 个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的;

2.       有些棋子是固定的,有些棋子则是可以移动的;

3.       任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。

游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。

给定一个棋盘,游戏可以玩 q 次,当然,每次棋盘上固定的格子是不会变的,但是棋盘上空白的格子的初始位置、指定的可移动的棋子的初始位置和目标位置却可能不同。第 i 次玩的时候,空白的格子在第 EXi 行第 EYi 列,指定的可移动棋子的初始位置为第 SXi 行第 SYi 列,目标位置为第 TXi 行第 TYi 列。

假设小 B 每秒钟能进行一次移动棋子的操作,而其他操作的时间都可以忽略不计。请

你告诉小 B 每一次游戏所需要的最少时间,或者告诉他不可能完成游戏。

Input

第一行有 3 个整数,每两个整数之间用一个空格隔开,依次表示 n、m 和 q;
接下来的 n 行描述一个 n*m 的棋盘,每行有 m 个整数,每两个整数之间用一个空格隔开,每个整数描述棋盘上一个格子的状态,0 表示该格子上的棋子是固定的,1 表示该格子上的棋子可以移动或者该格子是空白的。
接下来的 q 行,每行包含 6 个整数依次是 EXi、EYi、SXi、SYi、TXi、TYi,每两个整数之间用一个空格隔开,表示每次游戏空白格子的位置,指定棋子的初始位置和目标位置。

Output

输出有 q 行,每行包含 1 个整数,表示每次游戏所需要的最少时间,如果某次游戏无法完成目标则输出−1。

Sample Input

3 4 2
0 1 1 1
0 1 1 0
0 1 0 0
3 2 1 2 2 2
1 2 2 2 3 2

Sample Output

2
-1

HINT

【输入输出样例说明】

棋盘上划叉的格子是固定的,红色格子是目标位置,圆圈表示棋子,其中绿色圆圈表示目标棋子。

1.第一次游戏,空白格子的初始位置是 (3, 2)(图中空白所示),游戏的目标是将初始位置在(1, 2)上的棋子(图中绿色圆圈所代表的棋子)移动到目标位置(2, 2)(图中红色的格子)上。

2.第二次游戏,空白格子的初始位置是(1, 2)(图中空白所示),游戏的目标是将初始位置在(2, 2)上的棋子(图中绿色圆圈所示)移动到目标位置 (3, 2)上。

要将指定块移入目标位置,必须先将空白块移入目标位置,空白块要移动到目标位置,必然是从位置(2,2)上与当前图中目标位置上的棋子交换位置,之后能与空白块交换位置的只有当前图中目标位置上的那个棋子,因此目标棋子永远无法走到它的目标位置,游戏无法完成。

【数据范围】

对于 30%的数据,1 ≤ n, m ≤ 10,q = 1;

对于 60%的数据,1 ≤ n, m ≤ 30,q ≤ 10;

对于 100%的数据,1 ≤ n, m ≤ 30,q ≤ 500。

Source

NOIP2013提高T6

题意:可以想象成首领之傲用R来拉箱子,要把箱子从初始位置拉到指定位置。能则输出最短步数,不能则输出 -1 。

题解:因为只有一个格子是空的,所以我们可以理解为将空白块移动到挨着指定块的位置,然后互换位置,有目的性地重复此操作,直到指定块归位。

首先我们可以想到利用搜索来解题,因为时间复杂度是O(p*n*m*n*m),即4*10^8,所以只好放弃。

这时候我们就想到了A*优化和最短路优化。

(p.s.,要看正解直接“page down”,看到“最短路”再停!)

A* : (不要着急说它是错的,虽然它的确是错的,不乐意看可以直接略过此处到最短路优化一节)很简单,照裸搜来写,然后把估价函数写好就行了。

首先bfs n*m次得出图中任意两点距离dist[][]。然后因为当指定块被空白块转换后,空白块需要至少两步才能到达指定块的另一侧,然后互换位置又是一步,所以我的估价函数写的是dist[a1][b1][x2][y2]*3+dist[a0][b0][a1][b1]即【指定块距离目标位置距离*3+空白块到被移动格子距离*1】。

而状态visit[a][b][c][d]记录的则是指定块在(a,b),空白快在(c,d)时的状态。

代码一60分(visit记录每个状态的最短移动距离)

(由于要省时间,这两个错了算法的代码都是手写堆,pq版删掉了)

#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#define N 35
#define NN 1000
using namespace std;struct Fiona{int f,w,x0,y0,x1,y1;Fiona(int i1,int i2,int i3,int i4,int i5,int i6):f(i1),w(i2),x0(i3),y0(i4),x1(i5),y1(i6){}Fiona(){}};struct Vayne{int x,y;Vayne(int a,int b):x(a),y(b){}};int n,m,q,cnt;int visit[N][N][N][N],block[N][N];int dist[N][N][N][N];int direct[4][2]={{1,0},{0,1},{-1,0},{0,-1}};int x0,x1,x2;int y0,y1,y2;
int eva(int a0,int b0,int a1,int b1)/*估价:空白块和指定块*/
{return dist[a1][b1][x2][y2]*2+dist[a0][b0][a1][b1];
}
Fiona heap[NN*NN],c;
void insert(Fiona X)
{int t=++cnt;for(heap[t]=X;heap[t].f<heap[t>>1].f;t>>=1)c=heap[t],heap[t]=heap[t>>1],heap[t>>1]=c;
}
void pop()
{int t=1,son;for(heap[t]=heap[cnt--];(t<<1)<=cnt;t=son){son=(t<<1==cnt||heap[t<<1].f<heap[t<<1|1].f)?t<<1:t<<1|1;if(heap[son].f<heap[t].f)c=heap[t],heap[t]=heap[son],heap[son]=c;else break;}
}
void priority_bfs()
{int i,j,vx,vy,x,y,w,cx,cy;scanf("%d%d%d%d%d%d",&x0,&y0,&x1,&y1,&x2,&y2);if(x1==x2&&y1==y2){printf("0\n");return ;}if(dist[x0][y0][x1][y1]>NN*NN||dist[x1][y1][x2][y2]>NN*NN){printf("-1\n");return ;}cnt=0;memset(visit,0x11,sizeof(visit));Fiona U(eva(x0,y0,x1,y1),0,x0,y0,x1,y1);visit[x1][y1][x0][y0]=0;insert(U);while(cnt){U=heap[1];pop();w=U.w+1;x=U.x0;y=U.y0;cx=U.x1;cy=U.y1;for(i=0;i<4;i++){vx=x+direct[i][0];vy=y+direct[i][1];if(!block[vx][vy])continue;if(vx==cx&&vy==cy){if(visit[x][y][cx][cy]>w){if(x==x2&&y==y2){printf("%d\n",w);return ;}visit[x][y][cx][cy]=w;insert(Fiona(eva(cx,cy,x,y)+w,w,cx,cy,x,y));}}else if(visit[cx][cy][vx][vy]>w){visit[cx][cy][vx][vy]=w;insert(Fiona(eva(vx,vy,cx,cy)+w,w,vx,vy,cx,cy));}}}printf("-1\n");
}void prepare()
{int i,j,k,x,y,vx,vy;Vayne U(0,0);for(i=1;i<=n;i++){for(j=1;j<=m;j++){queue<Vayne>q;q.push(Vayne(i,j));dist[i][j][i][j]=0;while(!q.empty()){U=q.front();q.pop();x=U.x;y=U.y;for(k=0;k<4;k++){vx=x+direct[k][0];vy=y+direct[k][1];if(dist[i][j][vx][vy]>1000&&block[vx][vy]){dist[i][j][vx][vy]=dist[i][j][x][y]+1;q.push(Vayne(vx,vy));}}}}}
}int main()
{freopen("puzzle.in","r",stdin);freopen("puzzle.ans","w",stdout);memset(dist,0x11,sizeof(dist));int i,j;scanf("%d%d%d",&n,&m,&q);for(i=1;i<=n;i++)for(j=1;j<=m;j++){scanf("%d",&block[i][j]);}prepare();for(i=1;i<=q;i++){priority_bfs();}return 0;
}

呵呵,20个点只过了前12个,60分。

代码二60分(visit记录是否到过某个状态,这个有明显缺陷,因为有的状态对,即两个状态间可能估价小的实际距离大,所以不能保证第一次搜到某个状态就是最优~)

#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#define N 35
#define NN 1000
using namespace std;struct Fiona{int f,w,x0,y0,x1,y1;Fiona(int i1,int i2,int i3,int i4,int i5,int i6):f(i1),w(i2),x0(i3),y0(i4),x1(i5),y1(i6){}Fiona(){}};struct Vayne{int x,y;Vayne(int a,int b):x(a),y(b){}};int n,m,q,cnt;int visit[N][N][N][N],block[N][N];int dist[N][N][N][N];int direct[4][2]={{1,0},{0,1},{-1,0},{0,-1}};int x0,x1,x2;int y0,y1,y2;
int eva(int a0,int b0,int a1,int b1)/*估价:空白格和被动格*/
{return dist[a1][b1][x2][y2]*3+dist[a0][b0][a1][b1];
}
Fiona heap[NN*NN],c;
void insert(Fiona X)
{int t=++cnt;for(heap[t]=X;heap[t].f<heap[t>>1].f;t>>=1)c=heap[t],heap[t]=heap[t>>1],heap[t>>1]=c;
}
void pop()
{int t=1,son;for(heap[t]=heap[cnt--];(t<<1)<=cnt;t=son){son=(t<<1==cnt||heap[t<<1].f<heap[t<<1|1].f)?t<<1:t<<1|1;if(heap[son].f<heap[t].f)c=heap[t],heap[t]=heap[son],heap[son]=c;else break;}
}
void priority_bfs(int cases)
{int i,vx,vy,x,y,w,cx,cy;scanf("%d%d%d%d%d%d",&x0,&y0,&x1,&y1,&x2,&y2);if(x1==x2&&y1==y2){printf("0\n");return ;}if(dist[x0][y0][x1][y1]>NN*NN||dist[x1][y1][x2][y2]>NN*NN){printf("-1\n");return ;}cnt=0;Fiona U(eva(x0,y0,x1,y1),0,x0,y0,x1,y1);visit[x1][y1][x0][y0]=cases;insert(U);while(cnt){U=heap[1];pop();w=U.w+1;x=U.x0;y=U.y0;cx=U.x1;cy=U.y1;for(i=0;i<4;i++){vx=x+direct[i][0];vy=y+direct[i][1];if(!block[vx][vy])continue;if(vx==cx&&vy==cy){if(visit[x][y][cx][cy]!=cases){if(x==x2&&y==y2){printf("%d\n",w);return ;}visit[x][y][cx][cy]=cases;insert(Fiona(eva(cx,cy,x,y)+w,w,cx,cy,x,y));}}else if(visit[cx][cy][vx][vy]!=cases){visit[cx][cy][vx][vy]=cases;insert(Fiona(eva(vx,vy,cx,cy)+w,w,vx,vy,cx,cy));}}}printf("-1\n");
}void prepare()
{int i,j,k,x,y,vx,vy;Vayne U(0,0);for(i=1;i<=n;i++){for(j=1;j<=m;j++){queue<Vayne>q;q.push(Vayne(i,j));dist[i][j][i][j]=0;while(!q.empty()){U=q.front();q.pop();x=U.x;y=U.y;for(k=0;k<4;k++){vx=x+direct[k][0];vy=y+direct[k][1];if(dist[i][j][vx][vy]>1000&&block[vx][vy]){dist[i][j][vx][vy]=dist[i][j][x][y]+1;q.push(Vayne(vx,vy));}}}}}
}int main()
{freopen("puzzle.in","r",stdin);freopen("puzzle.ans","w",stdout);memset(dist,0x11,sizeof(dist));int i,j;scanf("%d%d%d",&n,&m,&q);for(i=1;i<=n;i++)for(j=1;j<=m;j++){scanf("%d",&block[i][j]);}prepare();for(i=1;i<=q;i++){priority_bfs(i);}return 0;
}

这个更呵呵了,同样过了前12个点,60分,但是还有WA的。

打击人的是代码三70分(不要A*的裸搜,同学写的):

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
using namespace std;
struct state
{int space_x,space_y,son_x,son_y,step;state(){space_x=space_y=son_x=son_y=step=0;}
};
bool hash[31][31][31][31];
int map[101][101];
int main()
{freopen("puzzle.in","r",stdin);freopen("puzzle.ans","w",stdout);register int i,j;int n,m,t;scanf("%d%d%d",&n,&m,&t);for(i=1;i<=n;++i)for(j=1;j<=m;++j)scanf("%d",&map[i][j]);queue<state> q;while(t--){memset(hash , 0 , sizeof(hash));int s_x,s_y,b_x,b_y,e_x,e_y;scanf("%d%d%d%d%d%d",&s_x,&s_y,&b_x,&b_y,&e_x,&e_y);hash[s_x][s_y][b_x][b_y] = 1;state begin;begin.space_x=s_x;begin.space_y=s_y;begin.son_x=b_x;begin.son_y=b_y;begin.step=0;q.push(begin);bool find=0;while(!q.empty()){state ins=q.front();q.pop();if(ins.son_x==e_x&&ins.son_y==e_y){printf("%d\n",ins.step);find=1;break;}for(i=0;i<4;++i){int tx=ins.space_x+dx[i];int ty=ins.space_y+dy[i];if((tx!=ins.son_x||ty!=ins.son_y)&&tx>=1&&tx<=n&&ty>=1&&ty<=m){if((tx!=ins.son_x||ty!=ins.son_y)&&map[tx][ty])if(!hash[tx][ty][ins.son_x][ins.son_y]){hash[tx][ty][ins.son_x][ins.son_y] = 1;state tmp;tmp.space_x=tx;tmp.space_y=ty;tmp.son_x=ins.son_x;tmp.son_y=ins.son_y;tmp.step=ins.step+1;q.push(tmp);}}}if(abs(ins.space_x-ins.son_x)+abs(ins.space_y-ins.son_y)==1){int tx=ins.space_x;int ty=ins.space_y;if(!hash[ins.son_x][ins.son_y][tx][ty]){hash[ins.son_x][ins.son_y][tx][ty] = 1;state tmp;tmp.space_x=ins.son_x;tmp.space_y=ins.son_y;tmp.son_x=tx;tmp.son_y=ty;tmp.step=ins.step+1;q.push(tmp);}}}if(!find) printf("-1\n");q = queue<state>();}return 0;
}

这个代码70分,分析一下,是因为A*有个log级别维护最值的常数,所以反而慢了些(不要着急反驳说还有更多的原因)

真正让我放弃A*的是当我把估价函数写成return 0时,代码竟然变快了?!!于是我就开始认真分析A*的优劣了。

总结:A*适合冗余状态较多(,估价函数好写)的搜索,这样可以删减去很多没用的搜索(搜索方向),这一切,盖因它是一种有目的性,或者说有方向性的搜索,而估价函数赋予了它这种方向性。同时有一个小总结就是,A*需要:在最优路径上,每个状态的估价函数值需要保持非严格递增(当然严格更好),否则若在最优路径上估价函数值是波动的,则可能走错方向,导致反而增添了许多冗余的搜索!于是,这题还写搜索?还写A*?还写双向BFS?见鬼去吧,最短路才可以拯救你。

最短路:这道题的图其实是一张n*m的图,动态加障碍(指定块),然后bfs搜索转移状态,所以我们完全可以预处理一遍,加边,然后跑最短路。

那么该如何加边呢?

啊,很简单,不要想太难。两个比较有用的状态之间加容易加的边就好了。什么叫有用的状态呢?就是一个“空白块挨着指定块”状态!

此题加的边为一个 “有用状态” 到一个指定块与其相邻的 “有用状态” ,然后每次询问连源连汇,万事大吉。

附代码,不懂自己看,或者手调,不是很难理解。

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define N 35
#define NN 7000
#define M 25000
#define inf 0x3f3f3f3f
using namespace std;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
struct Syndra
{int u,v,len,next;
}e[M];
struct Fiona
{int x,y;Fiona(int a,int b):x(a),y(b){}Fiona(){}
};
struct Vayne
{int f,v;Vayne(int a,int b):f(a),v(b){}Vayne(){}bool operator < (const Vayne& a)const{return a.f<f;}
};
int head[NN],id[N][N][N],cnt,num;
int map[N][N];
int n,m,query;
queue<Fiona>q;
queue<int>Q;
priority_queue<Vayne> pq;
int dis[N][N],dist[NN],in[NN];
void add(int u,int v,int len)
{cnt++;e[cnt].u=u;e[cnt].v=v;e[cnt].len=len;e[cnt].next=head[u];head[u]=cnt;
}
int bfs(int sx,int sy,int tx,int ty)/*已检查,绝对正确*/
{int i,vx,vy;if(sx==tx&&sy==ty)return 0;if(!map[sx][sy]||!map[tx][ty])return inf;while(!q.empty())q.pop();memset(dis,0x3f,sizeof(dis));q.push(Fiona(sx,sy));dis[sx][sy]=0;while(!q.empty()){Fiona U=q.front();q.pop();for(i=0;i<4;i++){vx=U.x+dir[i][0];vy=U.y+dir[i][1];if(dis[vx][vy]>dis[U.x][U.y]+1&&map[vx][vy]){dis[vx][vy]=dis[U.x][U.y]+1;if(vx==tx&&vy==ty)return dis[vx][vy];q.push(Fiona(vx,vy));}}}return inf;
}int pqspfa(int s,int t)
{int i,u,v;Vayne X;memset(dist,0x3f,sizeof(dist));memset(in,0,sizeof(in));while(!pq.empty())pq.pop();pq.push(Vayne(0,s));dist[s]=0;in[s]=1;while(!pq.empty()){X=pq.top();pq.pop();u=X.v;in[u]=0;for(i=head[u];i;i=e[i].next){v=e[i].v;if(dist[v]>dist[u]+e[i].len){dist[v]=dist[u]+e[i].len;if(!in[v])pq.push(Vayne(dist[v],v)),in[v]=1;}}}return dist[t]<inf?dist[t]:-1;
}int spfa(int s,int t)/*已检查,绝对正确*/
{int i,u,v;memset(dist,0x3f,sizeof(dist));memset(in,0,sizeof(in));while(!Q.empty())Q.pop();Q.push(s);dist[s]=0;in[s]=1;while(!Q.empty()){u=Q.front();Q.pop();in[u]=0;for(i=head[u];i;i=e[i].next){v=e[i].v;if(dist[v]>dist[u]+e[i].len){dist[v]=dist[u]+e[i].len;if(!in[v])Q.push(v),in[v]=1;}}}return dist[t]<inf?dist[t]:-1;
}
void build()/*已检查,绝对正确*/
{int i,j,k,l,i1,j1,i2,j2;int temp;scanf("%d%d%d",&n,&m,&query);for(i=1;i<=n;i++){for(j=1;j<=m;j++){scanf("%d",&map[i][j]);for(k=0;k<4;k++)id[i][j][k]=++num;}}for(i=1;i<=n;i++){for(j=1;j<=m;j++)if(map[i][j]){map[i][j]=0;for(k=0;k<4;k++)if(map[i1=i+dir[k][0]][j1=j+dir[k][1]]){for(l=k;l<4;l++)if(map[i2=i+dir[l][0]][j2=j+dir[l][1]]){temp=bfs(i1,j1,i2,j2)+1;if(temp<inf){add(id[i][j][k],id[i2][j2][l^1],temp);if(k!=l)add(id[i][j][l],id[i1][j1][k^1],temp);}}}map[i][j]=1;}}/*上为优化,下为标程*/
/*int move[N][N][N][N];memset(move,0x3f,sizeof(move));for(i=1;i<=n;i++){for(j=1;j<=m;j++)if(map[i][j]){map[i][j]=0;for(k=0;k<4;k++)if(map[i1=i+dir[k][0]][j1=j+dir[k][1]]){for(l=0;l<4;l++)if(map[i2=i+dir[l][0]][j2=j+dir[l][1]]){move[i][j][k][l]=bfs(i1,j1,i2,j2)+1;}}map[i][j]=1;}}for(i=1;i<=n;i++)for(j=1;j<=m;j++){for(k=0;k<4;k++)for(l=0;l<4;l++){if(move[i][j][k][l]<inf)add(id[i][j][k],id[i+dir[l][0]][j+dir[l][1]][l^1],move[i][j][k][l]);}}
*/
}
void handle()/*已检查:绝对正确*/
{int i,s,t;int vx,vy,temp;int bx,by,sx,sy,tx,ty;while(query--){scanf("%d%d%d%d%d%d",&bx,&by,&sx,&sy,&tx,&ty);if(sx==tx&&sy==ty){printf("0\n");continue;}if(!map[sx][sy]||!map[tx][ty]){printf("-1\n");continue;}s=++num;t=++num;map[sx][sy]=0;for(i=0;i<4;i++){vx=sx+dir[i][0];vy=sy+dir[i][1];if(!map[vx][vy])continue;temp=bfs(bx,by,vx,vy);if(temp<inf)add(s,id[sx][sy][i],temp);}map[sx][sy]=1;for(i=0;i<4;i++)if(map[tx+dir[i][0]][ty+dir[i][1]])add(id[tx][ty][i],t,0);printf("%d\n",spfa(s,t));}
}
int main()/*这里不需要检查*/
{freopen("puzzle.in","r",stdin);freopen("puzzle.ans","w",stdout);build();handle();return 0;
}

另:这道题略坑,“卡优化”,上面代码spfa 0.84秒20组数据完成,pqspfa?1.6s+!

这里还有一个删节版,就是把没用的都删掉了

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define N 35
#define NN 7000
#define M 25000
#define inf 0x3f3f3f3f
using namespace std;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
struct Syndra
{int u,v,len,next;
}e[M];
struct Fiona
{int x,y;Fiona(int a,int b):x(a),y(b){}Fiona(){}
};
int head[NN],id[N][N][N],cnt,num;
int map[N][N];
int n,m,query;
queue<Fiona>q;
queue<int>Q;
int dis[N][N],dist[NN],in[NN];
void add(int u,int v,int len)
{cnt++;e[cnt].u=u;e[cnt].v=v;e[cnt].len=len;e[cnt].next=head[u];head[u]=cnt;
}
int bfs(int sx,int sy,int tx,int ty)
{int i,vx,vy;if(sx==tx&&sy==ty)return 0;if(!map[sx][sy]||!map[tx][ty])return inf;while(!q.empty())q.pop();memset(dis,0x3f,sizeof(dis));q.push(Fiona(sx,sy));dis[sx][sy]=0;while(!q.empty()){Fiona U=q.front();q.pop();for(i=0;i<4;i++){vx=U.x+dir[i][0];vy=U.y+dir[i][1];if(dis[vx][vy]>dis[U.x][U.y]+1&&map[vx][vy]){dis[vx][vy]=dis[U.x][U.y]+1;if(vx==tx&&vy==ty)return dis[vx][vy];q.push(Fiona(vx,vy));}}}return inf;
}int spfa(int s,int t)
{int i,u,v;memset(dist,0x3f,sizeof(dist));memset(in,0,sizeof(in));while(!Q.empty())Q.pop();Q.push(s);dist[s]=0;in[s]=1;while(!Q.empty()){u=Q.front();Q.pop();in[u]=0;for(i=head[u];i;i=e[i].next){v=e[i].v;if(dist[v]>dist[u]+e[i].len){dist[v]=dist[u]+e[i].len;if(!in[v])Q.push(v),in[v]=1;}}}return dist[t]<inf?dist[t]:-1;
}
void build()
{int i,j,k,l,i1,j1,i2,j2;int temp;scanf("%d%d%d",&n,&m,&query);for(i=1;i<=n;i++){for(j=1;j<=m;j++){scanf("%d",&map[i][j]);for(k=0;k<4;k++)id[i][j][k]=++num;}}for(i=1;i<=n;i++){for(j=1;j<=m;j++)if(map[i][j]){map[i][j]=0;for(k=0;k<4;k++)if(map[i1=i+dir[k][0]][j1=j+dir[k][1]]){for(l=k;l<4;l++)if(map[i2=i+dir[l][0]][j2=j+dir[l][1]]){temp=bfs(i1,j1,i2,j2)+1;if(temp<inf){add(id[i][j][k],id[i2][j2][l^1],temp);if(k!=l)add(id[i][j][l],id[i1][j1][k^1],temp);}}}map[i][j]=1;}}
}
void handle()
{int i,s,t;int vx,vy,temp;int bx,by,sx,sy,tx,ty;while(query--){scanf("%d%d%d%d%d%d",&bx,&by,&sx,&sy,&tx,&ty);if(sx==tx&&sy==ty){printf("0\n");continue;}if(!map[sx][sy]||!map[tx][ty]){printf("-1\n");continue;}s=++num;t=++num;map[sx][sy]=0;for(i=0;i<4;i++){vx=sx+dir[i][0];vy=sy+dir[i][1];if(!map[vx][vy])continue;temp=bfs(bx,by,vx,vy);if(temp<inf)add(s,id[sx][sy][i],temp);}map[sx][sy]=1;for(i=0;i<4;i++)if(map[tx+dir[i][0]][ty+dir[i][1]])add(id[tx][ty][i],t,0);printf("%d\n",spfa(s,t));}
}
int main()
{build();handle();return 0;
}

【NOIP2013】华容道 最短路优化搜索(spfa)相关推荐

  1. 队列优化dijsktra(SPFA)的玄学优化

    转载:大佬博客 最近想到了许多优化spfa的方法,这里想写个日报与大家探讨下 前置知识:spfa(不带任何优化) 由于使用较多 STLSTL ,本文中所有代码的评测均开启 O_2O2​ 优化 对一些数 ...

  2. BZOJ 4152 浅谈堆优化的SPFA算法

    世界真的很大 其实这道题一看就能想到最短路 关键是怎么建边 看一下数据,200000个点 每个点两两建边的话肯定会超时 好像说多了先看一下题吧: description 给定平面上的n个点,定义(x1 ...

  3. 2010提高组-乌龟棋 [记忆优化搜索]

    题目: 有n个格子,你有m张牌,每张牌上面有个数字,用了这张牌你就可以走这张牌上对应的数字了,每到达一个格子,你就会获得格子上相应的分数,问你如何合理的出牌,使分数最大化. 记忆优化搜索可能会好写一点 ...

  4. 记忆优化搜索(简单题)(洛谷P3183 [HAOI2016]食物链 )( P5635 【CSGRound1】天下第一 )

    昨天做了蓝桥杯的时候,发现自己对于记忆优化搜索甚是不熟悉,所以今天随便找了几个基础题做做,顺便写下两片题解,顺便用了一下devc++敲的代码,发现没有代码补全真的可以说是灰常难受了... 洛谷P318 ...

  5. 京东的商品搜索功能是如何实现的_【干货小知识】京东商家如何优化搜索流量?...

    在京东搜索流量是非常重要的一个入口,优化搜索流量时我们要从产品的标题先入手. ​ 首要保证的是你要做的关键词都在标题里面,然后分析客户的搜索习惯. 通常会有以下几种搜索情况: 1.搜索商品核心关键词+ ...

  6. [图论]最短路计数(spfa)

    最短路计数 Description 给出一个NN个顶点MM条边的无向无权图,顶点编号为1-N1−N.问从顶点11开始,到其他每个点的最短路有几条. Input 第一行包含22个正整数N,MN,M,为图 ...

  7. 【POJ2676】Sudoku(优化搜索顺序)

    problem 补全9*9的数独 满足每行,每列,每个3*3方格内1~9均只出现一次 solution 1.答案 状态:我们关心数独每个位置填了什么数.我们需要在每个状态中找出没有填的位置,检查有哪些 ...

  8. Pymoo:使用多目标优化搜索解集的实现方法

    Pymoo:使用多目标优化搜索解集的实现方法 一.优化问题的数学表述 二.Pymoo中求解最优化问题的实现 2.1 问题的实现 2.2 初始化算法(基于NSGA2遗传算法为例) 2.3 定义终止准则 ...

  9. 最短路——最短路计数(spfa)

    题目链接 最短路--最短路计数(spfa) 题目描述 给出一个 N 个顶点 M 条边的无向无权图,顶点编号为 1-N.问从顶点 1 开始,到其他每个点的最短路有几条. 输入格式 第一行包含 2 个正整 ...

最新文章

  1. Centos6.8防火墙配置
  2. Spring-AOP的五种通知和切面的优先级、通知变量声明
  3. birt预览能有内容发布后没内容_谷歌突然推出Android 11开发者预览版 新版带来部分新功能和改进...
  4. php300云,概述 · PHP300Framework2.0 · 看云
  5. Android 中的ORM框架
  6. udt java_Java DB中的Java用户定义类型(UDT)
  7. oracle输出一天所有秒数,Oracle函数通过秒数或分钟数获取时间段
  8. 小米盗图迪丽热巴?公关经理:占位示意 不存在故意盗图!
  9. android 微信支付过程,android 微信 支付 接入流程总结
  10. 「大学生学编程系列」第六篇:如何学习C语言?
  11. Java 操作 JSON
  12. python字典示例简单代码_python学习笔记:字典的使用示例详解
  13. 8 随机积分与随机微分方程
  14. Linux命令之find命令
  15. JLINK 驱动安装和配置ADS使用,ADX调试
  16. 计算机专业小米笔记本推荐,小米笔记本哪款好
  17. 冬奥会开幕式震撼刷屏,这些黑科技立了大功!
  18. Disk for DB is too low. Cassandra state detected DOWN. Disk space for DB not retrievable
  19. dialog 程序 表控制
  20. 第一个Andriod应用

热门文章

  1. 专有钉钉 浙政钉 前端 对接流程(小程序)
  2. 《把时间当作朋友》第1章读后感(一)
  3. 让时间成为自己的知心朋友\\《把时间当做朋友》读书笔记
  4. 【论文阅读】iSAM贝叶斯树相关内容理解与学习
  5. 插入数据报错:ISAM error:no free disk space
  6. 【论文学习】:ICCV 2017-Detect-and-Track: Efficient Pose Estimation in Videos
  7. Nginx 简易教程
  8. python 分词 jieba
  9. 给图片加边框源代码c语言,OpenCV实现给图片添加边框功能
  10. 2017.08.25【NOIP提高组】模拟赛B组