poj3126 prime path bfs

来源:互联网 发布:知乎 usb光驱 编辑:程序博客网 时间:2024/06/13 05:24

题目链接:http://poj.org/problem?id=3126

题意:给定两个范围在【1000,9999】的两个素数,问从一个素数到另外一个素数需要多少歩,每次只能改变一个数,且过渡的数必须是素数。例如:1033
——1733——3733——3739——3779——8779——8179。

分析:很经典的广搜题,谈到广搜不得不说的是已经搜索过的状态的标记,可以用visit数组,然后就是必须得是素数,可以先预处理,打印一张素数表,方便以后询问。注意四位数不能有前导0。其他的见代码:

code:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct node{int x,step;}s;
const int MAXN=10000;
bool is_prime[MAXN];
int visit[MAXN];
int begin,end;
void sieve(int n){
    for(int i=0;i<=n;i++)is_prime[i]=true;
    is_prime[0]=is_prime[1]=false;
    for(int i=2;i<=n;++i){
        if(is_prime[i]){
            for(int j=2*i;j<=n;j+=i)
                is_prime[j]=false;
        }
    }
}//素数筛方便以后询问
void bfs(){
        memset(visit,0,sizeof(visit));
        visit[begin]=1;
        queue<node>q;
        while(!q.empty())q.pop();
        s.step=0;s.x=begin;//初始化
        q.push(s);
        while(!q.empty()){
            node ne=q.front();q.pop();
            if(ne.x==end){
                printf("%d\n",ne.step);
                return ;
            }
            int a[4];//将一个完整的四位数分解成四个数字
            for(int i=3;i>=0;--i){
                a[i]=ne.x%10;
                ne.x/=10;
            }
            for(int i=0;i<4;++i){
                int j=(i==0?1:0);//如果是首位,那么不能为0,故从1开始枚举。
                for(;j<=9;++j){
                    int temp=a[i];
                    a[i]=j;
                    int num=a[0]*1000+a[1]*100+a[2]*10+a[3];//将分散的四个数字还原成一个完整的四位数
                    a[i]=temp;//将改变的数字复原,有点回溯的味道
                    if(!visit[num]&&is_prime[num]){
                        node no;no.step=ne.step+1;no.x=num;
                        visit[num]=1;
                        q.push(no);
                    }
                }
            }
        }
}
int main(){
    sieve(MAXN);
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%d",&begin,&end);
        bfs();
    }
}

0 0