题意:给一个表,问两个位置之间的最短距离是多少,其中素数位置不能经过。
思路:坐标范围是10000,也就是说这个表大约是100*100,当然题目中表是无穷大的,由于有些位置不能走实际上可能会大于100*100。这样构造一个大点的表判断一下素数位置,每次查询直接bfs求最短路即可。
#include <iostream> #include <string> #include <cstring> #include <cctype> #include <cstdio> #include <map> #include <stack> #include <cmath> #include <queue> #include <algorithm> #define UP 0 #define DOWN 1 #define LEFT 2 #define RIGHT 3 using namespace std; const int maxn=410; int g[maxn][maxn]; int vis[maxn][maxn]; const int mov[4][2]= {{-1,0},{1,0},{0,-1},{0,1}}; bool isPrime(int v) { int ed=sqrt(v); for(int i=2; i<=ed; ++i) if(v%i==0) return false; return true; } int nextDir(int d) { if(d==RIGHT) return UP; else if(d==UP) return LEFT; else if(d==LEFT) return DOWN; else if(d==DOWN) return RIGHT; } pair<int,int> pos[10005]; void init() { int val=0; int x=200,y=200; g[x][y]=++val; pos[val]=make_pair(x,y); int d=RIGHT; int len=2; while(len<=105) { for(int i=1; i<len; ++i) { x=x+mov[d][0]; y=y+mov[d][1]; ++val; if(isPrime(val)) g[x][y]=0; else { g[x][y]=val; if(val<=10000) pos[val]=make_pair(x,y); } } d=nextDir(d); for(int i=1; i<len; ++i) { x=x+mov[d][0]; y=y+mov[d][1]; ++val; if(isPrime(val)) g[x][y]=0; else { g[x][y]=val; if(val<=10000) pos[val]=make_pair(x,y); } } d=nextDir(d); ++len; } } int bfs(int st,int ed) { memset(vis,0,sizeof(vis)); queue<pair<int,int> > que; que.push(pos[st]); while(!que.empty()) { pair<int,int> p=que.front(); que.pop(); for(int i=0; i<4; ++i) { int nx=p.first+mov[i][0],ny=p.second+mov[i][1]; if(vis[nx][ny]||g[nx][ny]==0) continue; vis[nx][ny]=vis[p.first][p.second]+1; if(g[nx][ny]==ed) return vis[nx][ny]; que.push(make_pair(nx,ny)); } } return -1; } int main() { init(); int x,y,kase=0; while(scanf("%d%d",&x,&y)!=EOF) { printf("Case %d: ",++kase); if(x==y) printf("0\n"); else { int ans=bfs(x,y); if(ans==-1) puts("impossible"); else printf("%d\n",ans); } } return 0; }