题目
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;
}
}
}
}
}
}