POJ - 3126 - Prime Path

发布于 2024-06-10 16:23:48 字数 3523 浏览 27 评论 0

题目大意

第一个数 T 代表测试样例个数,下面每一行是一个测试样例,每行输入两个数 ab ,这两个数都是 1000~9999 之间的素数,现在要求你从第一个数变成第二个数,每次变换可以(只可以) 改变其中的一个数字,而且改变之后的那个数必须是素数,问能否经过有限次的这样变化,将第一个素数 a 变成第二个素数 b ,要你求最少的变化步数。

Sample Input

3
1033 8179
1373 8017
1033 1033

Sample Output

6
7
0

解析

相当于求无权图的最短路径(有权图用 dijkstra ),用 BFS 即可。

  • 筛素数可以使用 埃拉托斯特尼筛法 ,这个在 bfs 判断下一个节点进入队列时使用;
  • 然后主要就是每次变化四个数,每个数从 0~9 之间变化,得到下一个节点,然后判断是否满足条件,如果满足条件进队列即可。
import java.util.*;
import java.io.*;

public class Main {

    static class Clazz {
        public int num;
        public int step;

        public Clazz(int num, int step) {
            this.num = num;
            this.step = step;
        }
    }

    static final int MAX = 10000;

    static boolean[] sieve() {
        boolean[] is_prime = new boolean[MAX];
        Arrays.fill(is_prime, true);
        is_prime[0] = is_prime[1] = false;
        for (int i = 2; i < MAX; i++) {
            if (is_prime[i]) {
                for (int j = i * i; j < MAX; j += i)
                    is_prime[j] = false;
            }
        }
        return is_prime;
    }

    static int[] separate(int num) {
        int[] arr = new int[4];
        int i = 0;
        while (num > 0) {
            arr[i++] = num % 10;
            num /= 10;
        }
        return arr;
    }

    static int revert(int[] sep) {
        int res = 0;
        for (int i = 0; i < sep.length; i++)
            res += sep[i] * (int) Math.pow(10, i);
        return res;
    }

    static int bfs(int s, int e, boolean[] is_prime, boolean[] vis) {
        Queue<Clazz> queue = new LinkedList<Clazz>();
        queue.add(new Clazz(s, 0));
        vis[s] = true; // 和 dijkstra 不同, bfs 一开始标记为 true
        int[] aArr, bArr; // 两个数组
        while (!queue.isEmpty()) {
            Clazz cur = queue.poll();
            if (e == cur.num) {
                return cur.step;
            }
            aArr = separate(cur.num);
            for (int i = 0; i < 4; i++) {
                bArr = Arrays.copyOf(aArr, aArr.length);
                for (int j = 0; j < 10; j++) {
                    bArr[i] = j;
                    int nxtNum = revert(bArr);
                    if (nxtNum > 1000 && nxtNum < 10000 && nxtNum != cur.num && !vis[nxtNum] && is_prime[nxtNum]) {
                        vis[nxtNum] = true;
                        queue.add(new Clazz(nxtNum, cur.step + 1));
                    }
                }
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        int T = cin.nextInt();
        while (T-- > 0) {
            int s = cin.nextInt();
            int e = cin.nextInt();
            boolean[] is_prime = sieve(); // 筛选 0~10000 的素数
            boolean[] vis = new boolean[MAX];
            int res = bfs(s, e, is_prime, vis);
            System.out.println(res == -1 ? "Impossible" : res);
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

昔梦

暂无简介

文章
评论
25 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文