6.质数路径(简单搜索 BFS)

发布时间 2023-05-02 01:13:22作者: 风雨zzm

质数路径

题目链接

题目

给定两个四位质数 \(A\)\(B\) ,你需要通过最少的操作次数将 \(A\) 变为 \(B\) 。每次操作只能改变当前数的其中一位数字,并且每次操作过后,当前数必须仍然是一个质数。例如,将 \(1033\) 变为 \(8179\) ,最少需要进行 \(6\) 次操作,具体操作为:
1033 -> 1733 -> 3733 -> 3739 -> 3779 -> 8779 -> 8179
请计算并输出所需要的最少操作次数。

输入格式

第一行包含整数 \(T\) ,表示共有 \(T\) 组测试数据。
每组数据占一行,包含两个四位质数 \(A\)\(B\)

输出格式

每组数据输出一行答案,表示所需最少操作次数。
如果无法做到,则输出 Impossible
经实际测试,不存在无解情况,特此声明。

数据范围

\(1≤T≤100\)
\(1000≤A,B≤9999\),保证 \(A\)\(B\) 都是质数。

输入样例:

3
1033 8179
1373 8017
1033 1033

输出样例:

6
7
0

思路

从质数起点开始搜索,通过 \(BFS\) 每次向后每次扩展 \(4*9=36\) 种情况 ,同时更新最短距离

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int prime[N];
int d[N];//存最短距离
bool st[N];
int cnt;
void getprime(int n)//筛质数
{
	for(int i=2;i<=n;i++)
	{
		if(!st[i])prime[cnt++]=i;
		for(int j=0;prime[j]<=n/i;j++)
		{
			st[prime[j]*i]=true;
			if(i%prime[j]==0)break;
		}
	}
}

void bfs(int x)
{
	memset(d,-1,sizeof d);
	queue<int>q;
	q.push(x);
	d[x]=0;
	
	while(q.size())
	{
		auto t=q.front();
		q.pop();
		
		string s=to_string(t);
		for(int i=0;i<s.size();i++)//枚举每个位置
		{
			for(char j='0';j<='9';j++)//枚举数字0-9
			{
				if(s[i]==j)continue;//当前位置与原来位置的数相同就跳过
				string tem=s;
				tem[i]=j;//改变一位数字
				int x=stoi(tem);
				if(st[x]||d[x]!=-1)continue;//如果改变后的数不是质数,或者已经被搜索过,就跳过该数
				d[x]=d[t]+1;//更新最短距离
				
				q.push(x);
			}
		}
	}
}

int main()
{
	getprime(N);
	
	int T;
	cin>>T;
	while(T--)
	{
		int a,b;
		cin>>a>>b;
		bfs(a);
		if(d[b]==-1)puts("Impossible");
		else cout<<d[b]<<endl;
	}
	
	return 0;
}