sicily--1444(广度优先搜索)

本文介绍了一种使用广度优先搜索算法解决特定问题的方法,即在一个四位数范围内找到从一个素数变换到另一个素数所需的最少步骤,通过改变数字的一位来实现变换,并确保每个中间结果也是素数。

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

第一个问题,使用memset()函数必须加上 #include<cstring>, 否则 sicily编译失败;第二个问题,题目没有说明开始的数字就一定比结束的数字小,看到例子我就想当然了!

最后,为了能提高小小的效率,还是要每步都判断一下,剪枝;

思路:从起点开始,找出当改变一位能获取到的“素数”,判断是否已寻找到了,若是则结束;否则,将其推入队列中;从队列中的头部开始遍历,逐渐改变每一位,获取下一个能获得的“素数”

#include<iostream>
#include<queue>
#include<cstring>//没加这个sicily编译不过(memset)
using namespace std;

/*用于标记从0开始到9999是否被访问过了*/
bool visited[10000];

/*将非素数的访问设置为已访问,即不再去访问非素数*/
void RejectNotPrime()
{
    visited[1] = 1;
    for(int i = 2; i <= 100; i++)
    {
      for(int j = i; j <= 10000/i; j++ )
      {
          /*若能由i*j 组成则其一定不是素数*/
          visited[i * j] = 1;
      }
    }
}
/*广度优先搜索
**返回值即是从“起点”到“终点”所需的步骤
**/
int BFS(int start, int end)
{
    /*起点与终点一致,长度为0*/
    if(start == end)
    {
        return 0;
    }
    else
    {
		//题目中并没有说一定要从小变到大!!!!!!!!!!!
		//if(start < end)
            /*用于记录某个数被访问到时所需要的步骤数目*/
            int time[10000] = {0};
            /*白色为未访问,灰色为未完成,黑色为访问完成*/
            /*waiting 用来储存“灰色”的元素*/
            queue<int> waiting;
            /*将起点首先设为灰色,即将搜索start 当改变一位即可得到一个新的素数*/
            waiting.push(start);
            /*只要waiting 队列不为空,即说明有可能搜索未结束,仍未找到“终点”*/
            
            while(!waiting.empty())
            {
                /*searchNow 为当前考察的对象*/
                int searchNow;
                /*取“灰色”队列中的头元素作为考察对象*/
                searchNow = waiting.front();
                /*cout << searchNow << endl;*/
                waiting.pop();/*该数已考察完毕了*/
/*------------------------------------------------------------------------------------------*/

                /*得到“个位”*/
                int a = searchNow%10;/*a表示考察对象的个位*/
                int b = searchNow - a;/*b 表示考察对象减去个位后的数*/
                /*改变“个位”*/
                for(int i = 0; i < 10;  i ++)
                {
                    /*就是考察对象,不予理会*/
                    if(b + i == searchNow)
                    {
                        /*nothing*/
                    }
                    else
                    {
                        /*找到了“终点”, 函数可以返回步骤数了*/
                        if(b + i == end)
                        {
                            /*返回当前的步骤数*/
                            return time[searchNow] + 1;
                        }
                        /*既不是当前考察的数,也不是目标数*/
                        else
                        {
                            /*不是合数,也不是被访问过的数,将其入队列,即将其颜色改为“灰色”*/
                            if(!visited[b + i])
                            {
                                /*所需步骤为当前考察对象+1*/
                                time[b + i] = time[searchNow] + 1;
                                /*已访问过了*/
                                visited[b + i] = 1;
                                waiting.push(b +i);
                            }
                        }
                    }
                }
/*------------------------------------------------------------------------------------------*/
                /*获得“十位”*/
                int c = searchNow%100 - a;/*c 表示当前考察数的十位*10*/
                int d = searchNow - c;/*d 表示当前考察数除去十位后剩余的数*/
                /*改变“十位”*/
                for(int i = 0; i < 10; i++)
                {
                    /*就是考察对象,不予理会*/
                    if(d + i*10 == searchNow)
                    {
                        /*nothing*/
                    }
                    else
                    {
                        /*找到了“终点”, 函数可以返回步骤数了*/
                        if(d + i*10 == end)
                        {
                            /*返回当前的步骤数*/
                            return time[searchNow] + 1;
                        }
                        /*既不是当前考察的数,也不是目标数*/
                        else
                        {
                            /*不是合数,也不是被访问过的数,将其入队列,即将其颜色改为“灰色”*/
                            if(!visited[d + i*10])
                            {
                                /*所需步骤为当前考察对象+1*/
                                time[d + i*10] = time[searchNow] + 1;
                                /*已访问过了*/
                                visited[d + i*10] = 1;
                                waiting.push(d +i*10);
                            }
                        }
                    }
                }
/*------------------------------------------------------------------------------------------*/
                /*获得“百位”*/
                int e = searchNow%1000 - c - a;/*c 表示当前考察数的百位*100*/
                int f = searchNow - e;/*d 表示当前考察数除去百位位后剩余的数*/
                /*改变“百位”*/
                for(int i = 0; i < 10; i++)
                {
                    /*就是考察对象,不予理会*/
                    if(f + i*100 == searchNow)
                    {
                        /*nothing*/
                    }
                    else
                    {
                        /*找到了“终点”, 函数可以返回步骤数了*/
                        if(f + i*100 == end)
                        {
                            /*返回当前的步骤数*/
                            return time[searchNow] + 1;
                        }
                        /*既不是当前考察的数,也不是目标数*/
                        else
                        {
                            /*不是合数,也不是被访问过的数,将其入队列,即将其颜色改为“灰色”*/
                            if(!visited[f + i*100])
                            {
                                /*所需步骤为当前考察对象+1*/
                                time[f + i*100] = time[searchNow] + 1;
                                /*已访问过了*/
                                visited[f + i*100] = 1;
                                waiting.push(f +i*100);
                            }
                        }
                    }
                }
/*------------------------------------------------------------------------------------------*/
                /*获得“千位”*/
                int g = searchNow - e - c - a;/*c 表示当前考察数的千位*10*/
                int h = searchNow - g;/*d 表示当前考察数除去千位后剩余的数*/
                /*改变“千位”*/
                for(int i = 1; i < 10; i++)//千位不为0
                {
                    /*就是考察对象,不予理会*/
                    if(h + i*1000 == searchNow)
                    {
                        /*nothing*/
                    }
                    else
                    {
                        /*找到了“终点”, 函数可以返回步骤数了*/
                        if(h + i*1000 == end)
                        {
                            /*返回当前的步骤数*/
                            return time[searchNow] + 1;
                        }
                        /*既不是当前考察的数,也不是目标数*/
                        else
                        {
                            /*不是合数,也不是被访问过的数,将其入队列,即将其颜色改为“灰色”*/
                            if(!visited[h + i*1000])
                            {
                                /*所需步骤为当前考察对象+1*/
                                time[h + i*1000] = time[searchNow] + 1;
                                /*已访问过了*/
                                visited[h + i*1000] = 1;
                                waiting.push(h +i*1000);
                            }
                        }
                    }
                }

            }
        }
        
    
    /*说明没办法找到一个路径从start 到end*/
    return -1;
}
int main()
{
    int testNum;
    cin >> testNum;
    /*testNum-- 是先检测testNum 是否为0,接着再去减1操作*/
    while(testNum--)
    {
        /*设置全未访问*/
        memset(visited,0,sizeof(visited));
        /*先去除非素数的访问可能性*/
        RejectNotPrime();   
        int start, end;
        cin >> start >> end;
        int time = BFS(start, end);
        /*能找到一条路径*/
        if(time >= 0)
        {
            cout << time << endl;
        }
        else
        {
            cout << "Impossible"<< endl;
        }
        
    }
    return 0;
}                                 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值