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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值