Prime Path(POJ) 3126
(https://vjudge.net/problem/POJ-3126)
题目大意
给你两个四位数,且保证两个数为素数,要从第一个数变为第二个数。在变化过程中,
每次只能变化这个数的其中一位且变化后也为素数。求至少需要几次变化。
解题思路
首先求出在1000~9999之间的所有素数,存入一个一维数组。建立一个结构体储存当前
变化位置中的数和从起点到当前位置的步数。一个自定义函数来判断两个数是否只有一位
不相同,用于bfs。枚举所有1000~9999的素数,如果符合这个条件就存入队列中,用于
bfs。因为是广搜,所以可以保证步数最少。
AC代码
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define ll long long
using namespace std;
const int N=1e5;
int prime[N+10],num[N+10],flag[N+10],l=0,p[N+10],vis[N+10],v[N+10],zz;
struct IN
{
int val,cnt;
}Node;
void isprime() //求出素数 O(n)
{
for(int i=2;i<=N;i++)
{
if(!flag[i])
{
prime[++l]=i;
num[i]=l;
}
for(int j=1;j<=l;j++)
{
if(1ll*prime[j]*i>N)break;
flag[prime[j]*i]=1;
if(i%prime[j]==0)break;
}
}
}
void init() //用p数组存1000~9999的所有素数
{
int x=0;
for(int i=1;i<=N;i++)
{
if(prime[i]>1000)
{
p[x++]=prime[i];
}
if(prime[i]>=10000)break;
}
zz=x-1;
}
bool pd(int x,int y) //判断函数
{
int a[6],v=3,k=0;
a[0]=x/1000;
a[1]=x/100%10;
a[2]=x%100/10;
a[3]=x%10;
while(y!=0)
{
int u=y%10;
y/=10;
if(u!=a[v])k++;
v--;
}
if(k==1)return true;
else return false;
}
int bfs(int s,int t)
{
queue<IN>q;
IN node;
memset(vis,0,sizeof vis);
node.val=s;
node.cnt=0;
q.push(node);
vis[node.val]=1;
while(!q.empty())
{
IN cur=q.front();
q.pop();
if(cur.val==t)
{
return cur.cnt;
}
for(int i=0;i<zz;i++)
{
IN next=cur;
if(pd(next.val,p[i])==true&&vis[p[i]]==0)
{
vis[p[i]]=1;
next.cnt++;
next.val=p[i];
q.push(next);
}
}
}
return -1;
}
int main()
{
int t,w,e;
cin>>t;
isprime();
init();
while(t--){
cin>>w>>e;
if(bfs(w,e)<0){
printf("Impossible\n");
}else{
printf("%d\n",bfs(w,e));
}
}
return 0;
}
越自律,越自由