POJ 3126 Prime Path(BFS求“最短路”)

本文介绍了一种基于BFS算法解决素数变换问题的方法,通过构造特定的图结构,寻找两个四位素数间最短变换路径。文章详细阐述了解题思路及实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给出两个四位数的素数,按如下规则变换,使得将第一位数变换成第二位数的花费最少,输出最少值,否则输出0。      

  每次只能变换四位数的其中一位数,使得变换后的数也为素数,每次变换都需要1英镑(即使换上的数是以前被换下的)。

思路:若素数a可以按上述规则转化为b,则可以看做a、b直接有一条边。显然,从初始值到目标值的路径上的边数即为花费的      

   数目,这样一来,就相当于求最短路径。由于题目只要求最小花费数,所以不需要存储有向图。      

  用BFS搜索,每次枚举当前值x所能变换得到的值y,若y满足条件,将y以及从初始值达到当前y值所需要的次数压入队列。      

  只要当从队列取出的数值等于目标值,此时的花费即为答案,结束循环。

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>

using namespace std;

int start,goal,t;//start:初始值,goal:目标值
int prime[10001];
int vis[10001];//标记数i是否之前已经被转换过

struct Node{
    int num;
    int step; //从start变为num所需要的步数
};

//将x的第i位的值改成j
int change(int x,int i,int j){
    if(i==1)
        return x-x%10+j;
    if(i==2)
        return (x/100)*100+x%10+j*10;
    if(i==3)
        return (x/1000)*1000+x%100+j*100;
    if(i==4)
        return x%1000+j*1000;
    return 0;
}


int bfs(int start,int ends){
    queue<Node> q;
    Node a,b;
    vis[start]=1;
    a.num=start;
    a.step=0;
    q.push(a);
    while(!q.empty()){
        a=q.front();
        q.pop();
        //只要a.num等于目标值的话,就退出循环。
        //因为不可能有比这花费最少的情况了。
        if(a.num==ends){
            return a.step;
        }
        vis[a.num]=1;
        //枚举
        for(int i=1;i<=4;i++){
            for(int j=0;j<=9;j++){
                //若为偶数,直接继续
                if(i==1 && j%2==0)
                    continue;
                if(i==4&&j==0)
                    continue;
                int temp=change(a.num,i,j);
                if(prime[temp]==0 || vis[temp])
                    continue;
                b.num=temp;
                b.step=a.step+1;
                q.push(b);
            }
        }

    }
    return -1;
}
//预处理1000~9999的素数
void dealWithPrime(){
    memset(prime,1,sizeof(prime));
    for(int i=2;i<10000;i++){
        if(prime[i]){
            for(int j=i*i;j<10000;j+=i){
                prime[j]=0;
            }
        }
    }
}

int main()
{
    dealWithPrime();
    scanf("%d",&t);
    for(int i=1;i<=t;i++){
        scanf("%d%d",&start,&goal);
        memset(vis,0,sizeof(vis));
        int ans=bfs(start,goal);
        if(ans==-1)
            printf("0\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/chenxiwenruo/p/3364127.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值