【NOIP2013】华容道 最短路优化搜索(spfa)
华容道
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
Sample Output
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)相关推荐
- 队列优化dijsktra(SPFA)的玄学优化
转载:大佬博客 最近想到了许多优化spfa的方法,这里想写个日报与大家探讨下 前置知识:spfa(不带任何优化) 由于使用较多 STLSTL ,本文中所有代码的评测均开启 O_2O2 优化 对一些数 ...
- BZOJ 4152 浅谈堆优化的SPFA算法
世界真的很大 其实这道题一看就能想到最短路 关键是怎么建边 看一下数据,200000个点 每个点两两建边的话肯定会超时 好像说多了先看一下题吧: description 给定平面上的n个点,定义(x1 ...
- 2010提高组-乌龟棋 [记忆优化搜索]
题目: 有n个格子,你有m张牌,每张牌上面有个数字,用了这张牌你就可以走这张牌上对应的数字了,每到达一个格子,你就会获得格子上相应的分数,问你如何合理的出牌,使分数最大化. 记忆优化搜索可能会好写一点 ...
- 记忆优化搜索(简单题)(洛谷P3183 [HAOI2016]食物链 )( P5635 【CSGRound1】天下第一 )
昨天做了蓝桥杯的时候,发现自己对于记忆优化搜索甚是不熟悉,所以今天随便找了几个基础题做做,顺便写下两片题解,顺便用了一下devc++敲的代码,发现没有代码补全真的可以说是灰常难受了... 洛谷P318 ...
- 京东的商品搜索功能是如何实现的_【干货小知识】京东商家如何优化搜索流量?...
在京东搜索流量是非常重要的一个入口,优化搜索流量时我们要从产品的标题先入手. 首要保证的是你要做的关键词都在标题里面,然后分析客户的搜索习惯. 通常会有以下几种搜索情况: 1.搜索商品核心关键词+ ...
- [图论]最短路计数(spfa)
最短路计数 Description 给出一个NN个顶点MM条边的无向无权图,顶点编号为1-N1−N.问从顶点11开始,到其他每个点的最短路有几条. Input 第一行包含22个正整数N,MN,M,为图 ...
- 【POJ2676】Sudoku(优化搜索顺序)
problem 补全9*9的数独 满足每行,每列,每个3*3方格内1~9均只出现一次 solution 1.答案 状态:我们关心数独每个位置填了什么数.我们需要在每个状态中找出没有填的位置,检查有哪些 ...
- Pymoo:使用多目标优化搜索解集的实现方法
Pymoo:使用多目标优化搜索解集的实现方法 一.优化问题的数学表述 二.Pymoo中求解最优化问题的实现 2.1 问题的实现 2.2 初始化算法(基于NSGA2遗传算法为例) 2.3 定义终止准则 ...
- 最短路——最短路计数(spfa)
题目链接 最短路--最短路计数(spfa) 题目描述 给出一个 N 个顶点 M 条边的无向无权图,顶点编号为 1-N.问从顶点 1 开始,到其他每个点的最短路有几条. 输入格式 第一行包含 2 个正整 ...
最新文章
- Centos6.8防火墙配置
- Spring-AOP的五种通知和切面的优先级、通知变量声明
- birt预览能有内容发布后没内容_谷歌突然推出Android 11开发者预览版 新版带来部分新功能和改进...
- php300云,概述 · PHP300Framework2.0 · 看云
- Android 中的ORM框架
- udt java_Java DB中的Java用户定义类型(UDT)
- oracle输出一天所有秒数,Oracle函数通过秒数或分钟数获取时间段
- 小米盗图迪丽热巴?公关经理:占位示意 不存在故意盗图!
- android 微信支付过程,android 微信 支付 接入流程总结
- 「大学生学编程系列」第六篇:如何学习C语言?
- Java 操作 JSON
- python字典示例简单代码_python学习笔记:字典的使用示例详解
- 8 随机积分与随机微分方程
- Linux命令之find命令
- JLINK 驱动安装和配置ADS使用,ADX调试
- 计算机专业小米笔记本推荐,小米笔记本哪款好
- 冬奥会开幕式震撼刷屏,这些黑科技立了大功!
- Disk for DB is too low. Cassandra state detected DOWN. Disk space for DB not retrievable
- dialog 程序 表控制
- 第一个Andriod应用
热门文章
- 专有钉钉 浙政钉 前端 对接流程(小程序)
- 《把时间当作朋友》第1章读后感(一)
- 让时间成为自己的知心朋友\\《把时间当做朋友》读书笔记
- 【论文阅读】iSAM贝叶斯树相关内容理解与学习
- 插入数据报错:ISAM error:no free disk space
- 【论文学习】:ICCV 2017-Detect-and-Track: Efficient Pose Estimation in Videos
- Nginx 简易教程
- python 分词 jieba
- 给图片加边框源代码c语言,OpenCV实现给图片添加边框功能
- 2017.08.25【NOIP提高组】模拟赛B组