【专题一 简单搜索】6. Prime Path POJ-3126 Prime Path

该博客讨论了一个数学与编程相结合的问题,即如何找到两个四位质数之间变换次数最少的质数路径。通过埃拉托斯特尼筛法找出一定范围内的所有质数,然后使用广度优先搜索(BFS)策略,查找从起始质数到目标质数的质数路径,同时确保每次只改变一个数字且结果仍为质数。过程中使用哈希集合进行剪枝,以达到最小成本。文章提供了一个示例及解决方案,并展示了如何实现这个算法。
摘要由CSDN通过智能技术生成

题目

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.

输入

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).

输出

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

例子

eg1:
input:
1033 8179
output:
6

eg2:
input:
1373 8017
output:
7

eg3:
input:
1033 1033
output:
0

题目大意

首先任选两个质数 a、b。然后他可以对 a 执行一次位变更操作,将其中的某一位进行数字变换,将 a 变成另外一个位数相同的数 c。只有当 c 也是质数时他才会执行一次位变更操作。问最少需要经过多少次位变更操作才能使得 a 变为 b ?
eg:质数 1021 -> 质数 1409,转换过程为 1021 -> 1621 -> 1601 -> 1609 -> 1409,最少变换了 4 次。

思路

首先解决质数问题

先用埃氏筛选算出10000以内所有的质数

boolean[] primes;
int n = 10000;
void eratosthenesSieve() {
    primes = new boolean[n + 1];
    Arrays.fill(primes, true);
    primes[0] = primes[1] = false;
    for (int i = 2; i < Math.floor(Math.sqrt(n)); i++) {
        if (primes[i]) {
            for (int j = i * 2; j <= n; j += i) {
                primes[j] = false;
            }
        }
    }
}

然后遍历
拿1021为例
遍历个位为1020、1021、1022、1023、1024、1025、1026、1027、1028、1029
遍历十位为1001、1011、1021、1031、1041、1051、1061、1071、1081、1091
遍历百位为1021、1121、1221、1321、1421、1521、1621、1721、1821、1921
遍历千位为0021、1021、2021、3021、4021、5021、6021、7021、8021、9021

判断每个数字是不是质数,加入队列中,进行下一轮bfs

每遍历一个数字,都用一个hashmap来存储,用于剪枝

直到数字变换至和目标数字相同


public class t1_q6_Prime_Path {

    public static void main(String[] args) {
        Sloution s = new Sloution();
        int res = s.func(1021, 1409);
        System.out.println(res);
    }


    static class Sloution {
        boolean[] primes;
        int n = 10000;

        int func(int a, int b) {
            eratosthenesSieve();
            return bfs(a, b);
        }

        int bfs(int a, int b) {
            if (a == b) return 0;
            Deque<Integer> q = new ArrayDeque<>();
            q.addLast(a);
            Set<Integer> set = new HashSet<>();
            set.add(a);
            int size = q.size(), t = 0;

            while (!q.isEmpty()) {
                for (int k = 0; k < size; k++) {
                    int m = q.pollFirst();
                    if (m == b) return t;
                    for (int j = 1; j <= 1000; j *= 10) {
                        int start = m / (j * 10) * (j * 10) + m % j;
                        int end = start + 9 * j;
                        for (int i = start; i <= end; i += j) {
                            if (i < 1000) continue;
                            if (!set.contains(i) && primes[i]) {
                                q.addLast(i);
                                set.add(i);
                            }
                        }
                    }
                }
                t++;
                size = q.size();
            }
            return -1;
        }


        void eratosthenesSieve() {
            primes = new boolean[n + 1];
            Arrays.fill(primes, true);
            primes[0] = primes[1] = false;
            for (int i = 2; i < Math.floor(Math.sqrt(n)); i++) {
                if (primes[i]) {
                    for (int j = i * 2; j <= n; j += i) {
                        primes[j] = false;
                    }
                }
            }
        }

    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Geek-Banana

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值