poj 3126 Prime Path 题解

参考博客https://www.xuebuyuan.com/2962927.html

27号 28号出去爬山了手头也不好带电脑= =,所以咕咕了两天(绝不是懒着不想写),今天把欠的题目补上。

 

poj 3126 题目大意 四位数从一个素数到另一个素数,通过1位1位的变动(变动一位距离加1),中间还只能走素数,请问最短距离?

 

其实很明显用BFS的思路去做,只不过给我们加了限定条件(只能是素数),而且是4位每一位都有10种路可以走。我一开始做这道题的时候就想这样的话每一个数有40条路可以走= =,emm感觉好大,但是好像对于这个确实没有什么好的优化方法,也只能硬着头皮去写,如果有什么别的好方法欢迎在评论中写出。

另外对于此题还是一个学习素数筛的好例题

https://blog.csdn.net/qq_41117236/article/details/81152055,这是我学习素数筛时看的博客,分类很详细,本代码中我还是采用了爱拉托斯尼特筛法(毕竟好写好理解= =) 复杂度是O(N*lnlnN)

底下两种算法是在批量检测一堆数是不是素数时的好总结,第一种就是判断单个数是不是素数的标准写法,做个模板用吧。

 

ac代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<set> 
#include<queue>

using namespace std;

int num,aim;

struct node
{
    int num,step;
}node_num,node_aim;                //step是所需距离 

const int maxn=1e5;
bool number[maxn+5];
void isprime(int N)
{
    int i,j;
    memset(number,true,sizeof(number));
    for(i=2;i<=sqrt(N*1.0);i++)
    {
        if(number[i]==true)
        {
            for(j=i*i;j<=N;j+=i)
                {
                number[j]=false;
                 
                }
            //二次筛选法:i是素数,则下一个起点是i*i,把后面的所有的i*i+2*n*i筛掉
        }
    
    }
    
}

int bfs()
{
    queue<node>q;
    q.push(node_num);
    set<int>s;
    s.insert(node_num.num);

    while(!q.empty())
    {
        node shu = q.front(); q.pop();

        for(int i = 0; i < 4; i ++)              //一共4位每一位都要进行9次变换(因为都让这位变为0) 
        {
            int P = (int)pow(10.0,i);            
            int digt = (shu.num/P)%10;
            int temp = shu.num - digt*P;         //这三步是为了让我们要操作的那一位变为0 
            for(int j = 0; j < 10; j ++)
            {
                if(i == 3 && j == 0) continue;   //首尾不能为0 
                int flag = temp+P*j;
                if(number[flag]==true && s.find(flag) == s.end())    //set.find()函数功能是在set中遍历如果没查到就返回set.end,以此来实现查重功能 
                {
                    node N;
                    N.num = flag;
                    N.step = shu.step+1;
                    if(flag == aim)  return N.step;
                    q.push(N);
                    s.insert(flag);
                }
            }
        }
    }
    return 0;

}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>num>>aim;
        isprime(9999);
        node_num.num = num;
        node_num.step = 0;
        cout<<bfs()<<endl;
    }
    return 0;
}

另外因为此题范围较小,可以把范围内的素数全部打表,但是那样还是要对每个素数判断是否只是相差一位来看能不能走(BFS限定条件),这样岂不是每一步可走的路更多了,本菜鸟还不太明白那样复杂度会降低吗,欢迎大家评论教我或者对本代码进行指正。

(其实是27日的题- -,day5)

posted @ 2019-09-29 17:07  hanny007  阅读(210)  评论(0编辑  收藏  举报