POJ-3126 Prime Path

来源:互联网 发布:用mac编程 编辑:程序博客网 时间:2024/05/23 12:01
#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;int t, op, ed;      //t为访问次数 op为第一个素数 ed为第二素数(即目标素数)int prime[10000];   //建立素数表int sign[10000];    //标记是否访问过int digit[4];       //分离每一位struct Step         //建立结构体{    int step;       //储存步数    int num;        //储存每一步的数} start;queue<Step> Number; //队列void prime_print()  //建立素数表 下标为素数的标记1 否则默认0{    memset(prime, 0, sizeof(prime));    for(int m = 1001; m <= 9999; m ++)    {        bool flag = true;        for(int i = 2; i * i <= m; i ++)            if(m % i == 0)            {                flag = false;                break;            }        if(flag)            prime[m] = 1;    }}int bfs()                       //bfs查询{    if(start.num == ed)         //初始位置若为ed直接输出0结束。    {        cout << start.step << endl;        return 1;    }    while(!Number.empty())      //清空队列        Number.pop();    Number.push(start);         //投入第一个元素    sign[start.num] = 1;        //第一个元素访问 标记1    while(!Number.empty())      //当队列不为0一直访问    {        Step now = Number.front();      //now一直存储队列第一个元素        Number.pop();                   //之后将此元素弹出 为下一次循环做准备        digit[0] = now.num / 1000;      //分离千位        digit[1] = now.num / 100 % 10;  //分离百位        digit[2] = now.num / 10 % 10;   //分离十位        digit[3] = now.num % 10;        //分离个位        for(int i = 0; i < 4; i ++)     //按每一位进行变化        {            int temp = digit[i];         //这只是为了方便变化 后边会变回去            for(int j = 0; j <= 9; j ++) //每一位从0~9变化            {                Step next = now;         //储存下一位                if((!i && !j) || (temp == j)) //前一个判断是排除千位为0的可能 后一个判断是如果变化的数与原来相同 则不做处理                    continue;                digit[i] = j;            //变化这一位                next.num = digit[0] * 1000 + digit[1] * 100 + digit[2] * 10 + digit[3]; //求和                if(!prime[next.num] || sign[next.num])  //如果这不是素数 或者 已经访问过了 则跳过下面步骤 进行下一次循环                    continue;                next.step ++;           //满足条件后 下一次步数+1                if(next.num == ed)      //如果下一个数与ed相等 则 直接输出 并 结束                {                    cout << next.step << endl;                    return 1;                }                else                    //如果还不能和ed相等 则继续                {                    Number.push(next);  //把next投入队列                    sign[next.num] = 1; //并把此数标记 已访问                }            }            digit[i] = temp;        //保证进行下一位变化时 这一位保持不变        }    }    return 0;}int main(){    prime_print();    scanf("%d", & t);               //输入进行次数    while(t --)    {        memset(sign, 0, sizeof(sign));  //初始访问标记数组        scanf("%d %d", & op, & ed);        start.step = 0;        start.num = op;        if(!bfs())                      //如果返回值为0 输出不可能            cout << "Impossible" << endl;    }    return 0;}

题意:给两个素数。之后要将前一个素数变为后一个素数。要求每步变动一位。且变动后的数也是素数。

题解:用bfs查最短路径 。此题让我对bfs理解更深入。一开始用pow简写×10 ×100 ...结果导致错误。好像pow有误差。搞了半天。

0 0