【POJ3126】Prime Path(预处理+BFS)

题面:【POJ3126】Prime Path

这道题目要在解决问题之前先预处理出一个四位数的质数表,由于范围很小,只需要枚举1000~9999并用O(√n)的质数判断函数进行验证即可,当然,用线性筛除余法也是可以的(此题时间充裕,不建议用MR素数判断)。

然后便是一个BFS,对于当前数字,只要枚举每一个它能变成的质数,判断是否已操作过,若未操作过则将其加入队列即可。

代码如下:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
#define LL long long
using namespace std;
int n,m;
bool vis[10000],Prime[10000];
struct BFS
{
	int v,step;//v存储数字,step存储步数 
};
queue<BFS> q,q_;
int read()
{
	int x=0,f=1;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if(ch=='-') f=-1,ch=getchar();
	while(ch>='0'&&ch<='9') (x*=10)+=ch-'0',ch=getchar();
	return x*=f;
}
void write(int x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+'0');
}
bool Is_prime(int x) {for(int i=2;i*i<=x;i++) if(!(x%i)) return false;return true;}//O(√n)的质数判断函数 
void Find_prime() {for(int i=1000;i<10000;i++) Prime[i]=Is_prime(i);}//枚举每一个四位数 
void bfs()//BFS 
{
	if(q.empty()) return;//若队列空了则退出函数(理论上来说是不会出现这种情况的) 
	if(q.front().v==m) {write(q.front().step),putchar('\n');return;}//达成目标就输出步数(记得换行) 
	for(int t=1;t<=1000;t*=10) for(int i=0;i<=9;i++) {int nx=q.front().v-(q.front().v/t)%10*t+i*t;if(!vis[nx]&&Prime[nx]) vis[nx]=true,q.push({nx,q.front().step+1});}//枚举当前数字能变成的每一个质数 
	q.pop(),bfs();//将当前状态从队列中取出,BFS下一个状态 
}
int main()
{
	memset(Prime,false,sizeof(Prime));
	Find_prime();//预处理出四位数的质数表 
	int T=read();
	while(T--)
	{
		n=read(),m=read();
		memset(vis,false,sizeof(vis));
		q=q_,q.push({n,0}),vis[n]=true;//记得在新的一次BFS前清空队列 
		bfs();
	}
	return 0;
}



版权声明:转载请注明地址


猜你喜欢

转载自blog.csdn.net/chenxiaoran666/article/details/80028341