POJ 3126 Prime Path【BFS】

<题目链接>

题目大意:

给你两个四位数,它们均为素数,以第一个四位数作为起点,每次能够变换该四位数的任意一位,变换后的四位数也必须是素数,问你是否能够通过变换使得第一个四位数变成第二个四位数。

解题分析:

先打一张素数表,然后进行BFS搜索,对于每次搜索的当前数,枚举某一位与它不同的所有数,判断它是否符合条件,如果符合,就将它加入队列,继续搜索。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<math.h>
#define min 0x3f3f3f3f

using namespace std;

int arr[10005];
int vis[10005];
int n,m;

void prim()     //素数打表
{
    int i,j;
    arr[0]=arr[1]=1;
    for(i=2;i<=10000;i++)
    {
        if(!arr[i])
        {
            for(j=i*2;j<=10000;j+=i)
            arr[j]=1;
        }
    }
}

int bfs(int first,int last)
{
    queue <int>q;
    int v,i,j,temp,vtemp,count[10005],N[4];
    memset(vis,0,sizeof(vis));
    memset(count,0,sizeof(count));
    q.push(first);
    vis[first]=1;
    while(!q.empty())
    {
        v=q.front();
        q.pop();
        N[0]=v/1000;
        N[1]=v%1000/100;
        N[2]=v%100/10;
        N[3]=v%10;          //N[]为v的各位数

        for(j=0;j<4;j++)
        {
            temp=N[j];
            for(i=0;i<10;i++)
                if(i!=temp)      //枚举某一位与当前数不同的数
                {
                    N[j]=i;
                    vtemp=N[0]*1000+N[1]*100+N[2]*10+N[3];
                    if(!vis[vtemp] && !arr[vtemp] && vtemp>1000)  //如果枚举的这个数没有枚举过,并且是一个四位数素数
                    {
                        vis[vtemp]=1;     //已经走过的就标记
                        count[vtemp]=count[v]+1;   //步数加一
                        q.push(vtemp);
                    }
                    if(vtemp==last) return count[vtemp];  //找到了最终的数
                }
            N[j]=temp;   //将原来的数还原,防止对下一步造成影响
        }
        if(v==last) return count[v];  //找到了最终的数
    }
    return -1;
}

int main()
{
    int t,k;
    cin>>t;
    prim();
    while(t--)
    {
        cin>>n>>m;
        k=bfs(n,m);
        if(k!=-1)
        cout<<k<<endl;
        else
        cout<<"Impossible"<<endl;
    }
    return 0;
}
 

下面是另一份代码,与上面枚举当前四位数的每一位数不同的是,这里用的是链式前向星储存某一个四位数能够转化成的所有下一个四位数。但是不知道为什么这份代码WA了。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;

const int maxn=10000+100; 

int isprime[maxn+1000];
int prime[maxn];
int top;
int n,m,ans;

void getprime(){
    top=0;
    memset(isprime,0,sizeof(isprime));
    for(int i=2;i<=sqrt(maxn*1.0);i++){
        if(!isprime[i]){
            for(int j=i*i;j<=maxn;j+=i){
                isprime[j]=1;
            }
        }
    }
    for(int i=1000;i<=9999;i++){       //打表找出四位数的素数
        if(!isprime[i]){
            prime[++top]=i;
        }
    }
}

const int N=1100;
struct EDGE{       //用链式前向星记录与当前点只有一位不同的素数,即记录当前数下一步能够转化成的数
    int to;
    int next;
}edge[N*N];        //因为我打了一下表,发现top的值接近1100,所以这里这样设数组的上界
int head[11000];
int cnt;

struct node{
    int loc;
    int step;
    node(int a=0,int b=0):loc(a),step(b){}
};
int vis[11000];

bool juge(int a,int b){        //判断这两个数是否只有某一位数不同
    int fp=0;
    while(a){
        int a1=a%10;
        int a2=b%10;
        a/=10;
        b/=10;
        if(a1==a2)fp++;
    }
    if(fp==3)return true;
    return false;
}

void init(){
    memset(head,-1,sizeof(head));
    cnt=0;
}

void add(int u,int v){
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}

bool bfs(){
    memset(vis,0,sizeof(vis));
    queue<node>q;
    q.push(node(n,0));
    while(!q.empty()){
        node now=q.front();
        q.pop();
        if(now.loc==m){       //找到了最终要找的数
            ans=now.step;
            return true;
        }
        if(vis[now.loc])continue;
        vis[now.loc]=1;
        for(int i=head[now.loc];i!=-1;i=edge[i].next){    //枚举下一步所有满足条件的数(已经预处理过了)
            int v=edge[i].to;
            if(vis[v])continue;
            q.push(node(v,now.step+1));
        }
    }
    return false;
}

int main(){
    getprime();
    int t;scanf("%d",&t);
    while(t--){
        init();
        int a,b;
        scanf("%d %d",&a,&b);
        for(int i=1;i<=top;i++){
            if(prime[i]==a)n=i;
            if(prime[i]==b)m=i;
        }
        for(int i=n;i<=m;i++){
            for(int j=n;j<=m;j++){
                if(juge(prime[i],prime[j])){     //预处理,找到当前数下一步能够转化的所有数
                    add(i,j);
                }
            }
        }
        if(bfs()){
            printf("%d\n",ans);
        }
        else printf("Impossible\n");
    }
    return 0;
}

2018-08-30

原文地址:https://www.cnblogs.com/00isok/p/9563383.html

时间: 2024-10-10 01:23:58

POJ 3126 Prime Path【BFS】的相关文章

poj 3126 Prime Path 【暴力BFS】

题意:给你一个4位数,再给你一个4位数,如前一个数的每次只移动一位,问你能不能将第一个数变成第二个. 转移条件:1,只能通过素数作为中转,2,每次移动一位. 如果找到输出最少的转移次数(或步数), 如果找不到输出Impossible. 策略:如题. 直接上代码: #include<stdio.h> #include<string.h> #include<queue> #define M 10005 using std::queue; int vis[10000]; in

POJ - 3126 - Prime Path(BFS)

Prime Path POJ - 3126 题意: 给出两个四位素数 a , b.然后从a开始,每次可以改变四位中的一位数字,变成 c,c 可以接着变,直到变成b为止.要求 c 必须是素数.求变换次数的最小值.(a,b,c都是四位数字,输入时没有前导零) 分析: 每次改变可以获得一个四位数c,然后如果c是素数并且之前没有出现过,那么我们把它放入队列即可. int f[10001]; int v[10001]; void init()//素数筛 { memset(f,0,sizeof f); fo

(简单) POJ 3126 Prime Path,BFS。

Description The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-digit room numbers on their offices. — It is a matter of security to change such things every now

POJ 3126 Prime Path(BFS)

Prime Path Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12060   Accepted: 6843 Description The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-dig

POJ 3126 Prime Path (bfs+欧拉线性素数筛)

Description The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-digit room numbers on their offices. - It is a matter of security to change such things every now

POJ 3126 Prime Path (BFS)

[题目链接]click here~~ [题目大意]给你n,m各自是素数,求由n到m变化的步骤数,规定每一步仅仅能改变个十百千一位的数,且变化得到的每个数也为素数 [解题思路]和poj 3278类似.bfs+queue,分别枚举个十百千的每一位就能够了,只是注意个位仅仅能为奇数,且千位从1開始 代码: #ifndef _GLIBCXX_NO_ASSERT #include <cassert> #endif #include <cctype> #include <cerrno&g

双向广搜 POJ 3126 Prime Path

POJ 3126  Prime Path Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16204   Accepted: 9153 Description The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change th

POJ 3126 Prime Path(素数路径)

p.MsoNormal { margin-bottom: 10.0000pt; font-family: Tahoma; font-size: 11.0000pt } h1 { margin-top: 5.0000pt; margin-bottom: 5.0000pt; text-align: left; font-family: 宋体; font-weight: bold; font-size: 24.0000pt } span.10 { font-family: "Times New Rom

POJ 3126 Prime Path SPFA

http://poj.org/problem?id=3126 题目大意: 给你两个四位的素数s和t,要求每次改变一个数字,使得改变后的数字也为素数,求s变化到t的最少变化次数. 思路: 首先求出所有4位素数. 对于两个素数之间,如果只相差一个数字,那么就建立图,(双向) 最后求最短路即可(可以SPFA也可以BFS) #include<cstdio> #include<cstring> #include<queue> #include<algorithm> u