POJ 1915题目描述:给定象棋棋盘的大小,起点及终点坐标,求棋子马走到终点的最短路大小。
(最大规模300*300)
题目分析:基础的BFS,设置last与tail用来纪录每一圈是否走完。
考虑到起点和终点是等价的,这时可以采用双向BFS。
#include <queue> #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; int dirx[8]={1,1,-1,-1,2,2,-2,-2}; int diry[8]={2,-2,2,-2,1,-1,1,-1}; struct point{ int x,y; int t; bool operator==(point &X){ return x==X.x&&y==X.y; } point(const point&X){ x = X.x; y = X.y; t = X.t; } point(int a = 0 ,int b = 0,int c = 0){ x = a,y = b,t = c; } }; class plant{ int n; point beg,en; bool vis1[305][305]; bool vis2[305][305]; public: bool init(){ if(scanf("%d",&n)!=1)return false; cin>>beg.x>>beg.y>>en.x>>en.y; beg.t = 0; en.t = 0; return true; } int solve(){ //if(beg==en)return 0; int t1,t2; memset(vis1,0, sizeof(vis1)); memset(vis2,0, sizeof(vis2)); return bfs(); } void set_vis(bool vis[305][305],point &X){ vis[X.x][X.y] = true; } void set_vis(bool vis[305][305],int a,int b){ vis[a][b] = true; } bool check(int i,int j,bool vis[305][305]){ return (i>=0&&i<n&&j>=0&&j<n&&!vis[i][j]); } int bfs(){ queue <point>ss1,ss2; ss1.push(beg); ss2.push(en); point last1 = beg,last2 = en; set_vis(vis1,beg); set_vis(vis2,en); point tail1 = beg,tail2 = en; int t1 = 0,t2 = 0; int nx,ny; while (!ss1.empty()||!ss2.empty()){ if(!ss1.empty()){ point tmp = ss1.front(); ss1.pop(); if(vis2[tmp.x][tmp.y]){ point temp; while (!ss2.empty()){ temp = ss2.front(); ss2.pop(); if(tmp==temp)break;//此轮最后一点在到达点之后,说明在到达点之前time未更新 if(temp==last2){//否则处理时间+1, t2++; break; } } return t1+t2; } for(int i = 0 ;i < 8 ; i++){ nx = tmp.x+dirx[i]; ny = tmp.y+diry[i]; if(check(nx,ny,vis1)){ ss1.push(point(nx,ny,tmp.t+1)); set_vis(vis1,nx,ny); tail1 = ss1.back(); } } if(tmp==last1){ t1++; last1 = tail1; } } if(!ss2.empty()){ point tmp = ss2.front(); ss2.pop(); if(vis1[tmp.x][tmp.y]){ point temp; while (!ss1.empty()){ temp = ss1.front(); ss1.pop(); if(tmp==temp)break; if(temp==last1){ t1++; break; } } return t1+t2; } for(int i = 0 ; i < 8 ; i++){ nx = tmp.x+dirx[i]; ny = tmp.y+diry[i]; if(check(nx,ny,vis2)){ ss2.push(point(nx,ny,tmp.t+1)); set_vis(vis2,nx,ny); tail2 = ss2.back(); } } if(tmp==last2){ t2++; last2 = tail2; } } } } }; plant ss; int main(){ int t; cin>>t; while (t--){ ss.init(); cout<<ss.solve()<<endl; } }
姑且算是面向对象编程吧,便于更快找出错误。