kuangbin专题一 简单搜索 质数路径(POJ-3126)

发布时间 2023-04-15 00:04:39作者: Amαdeus

Prime Path

Time Limit: 1000MS Memory Limit: 65536K

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 and then, to keep the enemy in the dark.
— But look, I have chosen my number 1033 for good reasons. I am the Prime minister, you know!
— I know, so therefore your new number 8179 is also a prime. You will just have to paste four new digits over the four old ones on your office door.
— No, it’s not that simple. Suppose that I change the first digit to an 8, then the number will read 8033 which is not a prime!
— I see, being the prime minister you cannot stand having a non-prime number on your door even for a few seconds.
— Correct! So I must invent a scheme for going from 1033 to 8179 by a path of prime numbers where only one digit is changed from one prime to the next prime.

Now, the minister of finance, who had been eavesdropping, intervened.
— No unnecessary expenditure, please! I happen to know that the price of a digit is one pound.
— Hmm, in that case I need a computer program to minimize the cost. You don't know some very cheap software gurus, do you?
— In fact, I do. You see, there is this programming contest going on... Help the prime minister to find the cheapest prime path between any two given four-digit primes! The first digit must be nonzero, of course. Here is a solution in the case above.
1033
1733
3733
3739
3779
8779
8179
The cost of this solution is 6 pounds. Note that the digit 1 which got pasted over in step 2 can not be reused in the last step – a new 1 must be purchased.

Input

One line with a positive number: the number of test cases (at most 100). Then for each test case, one line with two numbers separated by a blank. Both numbers are four-digit primes (without leading zeros).

Output

One line for each case, either with a number stating the minimal cost or containing the word Impossible.

Sample Input

3
1033 8179
1373 8017
1033 1033

Sample Output

6
7
0


题目大意

有多组数据,每组数据给两个质数 AB , 其中 A 为起点,B 为终点,每次操作可以更改某一数位上的数字,且更改之后整个数字仍旧是质数,当然还要保持整个数字一直都是四位数。求质数 A 到质数 B 的最少操作次数。



解题思路

很显然的BFS求最短步数模型,还是很简单的。需要注意的是当枚举到更改的是首位数字且将其更改为0的状态时,需要跳过。对于质数的判断,数字有且仅有四位,所以每次用试除法判断质数应该也是可以的,不过我闲得无聊,写了个线性筛质数,预处理求得所有一万以内的质数。不过一开始我还是翻车了一下,在获取更改后的数字时,我起初想偷懒先将数字转成 string ,然后将某一位改成指定数字,再转回 int ,结果在POJ上居然超时了??!!最后还是老老实实改成用一个临时数组存储每一位数字,更改指定位的数字后再还原的写法。

/*   一切都是命运石之门的选择  El Psy Kongroo  */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<functional>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<double, double> pdd;
typedef pair<string, pii> psi;
typedef __int128 int128;
#define x first
#define y second
const int inf = 0x3f3f3f3f, mod = 1e9 + 7;

int src, des;
const int N = 1e4;
int dist[N];
int prime[N], cnt;
bool st[N];

void get_primes(){
    st[1] = true;
    for(int i = 2; i < N; i ++ ){
        if(!st[i]) prime[cnt ++ ] = i;
        for(int j = 0; prime[j] <= N / i; j ++ ){
            st[prime[j] * i] = true;
            if(i % prime[j] == 0) break;
        }
    }
}

int get_n(int num, int digit, int k){
    int a[5], idx = 0, res = 0;
    while(idx <= 4) a[ ++ idx] = num % 10, num /= 10; //获取每一位数字
    a[k] = digit;   //更改从个位开始第k个数字 
    while(idx) res = res * 10 + a[idx -- ];    //还原更改后的数字

    return res;
}

int bfs(){
    if(src == des) return 0;

    memset(dist, -1, sizeof(dist));
    queue<int> q; q.push(src);
    dist[src] = 0;

    while(!q.empty()){
        int from = q.front();
        q.pop();

        for(int k = 1; k <= 4; k ++ )
            for(int digit = 0; digit <= 9; digit ++ ){
                if(k == 4 && !digit) continue;  //如果首位数字改成0 跳过
                int to = get_n(from, digit, k);
                if(st[to] || dist[to] != -1) continue;

                q.push(to);
                dist[to] = dist[from] + 1;

                if(to == des) return dist[to];
            }
    }

    return -1;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    get_primes();    //预处理筛质数

    int T; cin >> T;
    while(T -- ){
        cin >> src >> des;

        int res = bfs();

        cout << res << endl;
    }

    return 0;
}