POJ 3126 Prime Path(素数路径)
POJ 3126 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.
内阁部长对安全部长发表改变办公室四位数房间号码的声明感到诚惶诚恐。 — 随时换号码是安全的做法,毕竟暗潮四伏。 — 然而我选1033做法房间号是有理由的。我是首相(Prime minister),你懂的。 — 我知道,所以你的新号码8179也是一个素数(prime )。你只要在你办公室门上的旧号码前贴四个新数字就好了。 — 没那么简单。如果我把第一个数改成8,那么号码将变成8033,这可不是素数。 — 我懂,你是总理,有素数强迫症。 — 是啊!所以我必须找个通过素数路径从1033到8179的方法,就是只改变其中一个数,并从一个素数到另一个素数。 与此同时,财政部长正暗中观察。 — 别搞没必要的开销!一个数字可是要一英镑。 — 嗯,这种情况下我需要一个计算最小成本的程序。你知道有群廉价的软件大神吗? — 当然知道。你看,这里就有个算法比赛……帮助总理找出任意两个给定的四位素数间最便宜的素数路径!当然第一个数字不能为零。这是上述情况的解法。 1033 1733 3733 3739 3779 8779 8179 这种解法的成本是6镑。注意,第2步中的数字1不能在最后一步重新使用 - 必须买个新的1。
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).
第一行为一个正整数:测试用例的数量(最多100)。
随后每个测试用例,一行有两个以空格分隔的数。每个数皆为四位素数(无前导零)。
Output - 输出
One line for each case, either with a number stating the minimal cost or containing the word Impossible.
每个用例一行,一个表示最少花费的数或单词Impossible。
Sample Input - 输入样例
3 1033 8179 1373 8017 1033 1033
Sample Output - 输出样例
6 7 0
题解
一开始没判断是否可行还是A了,完全没有注意那个Impossible。
最初设想用DFS,然而感觉没有BFS方便。
打个素数表,做个标记,然后BFS就能出来了。
代码 C++
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #define mx 10000 5 char prim[mx] = { 1 }, data[4]; 6 int len[mx]; 7 void rdy(){ 8 int i, j; 9 for (i = 4; i < mx; i += 2) prim[i] = 1; 10 for (i = 3; i < mx; i += 2){ 11 if (prim[i]) continue; 12 for (j = i << 1; j < mx; j += i) prim[j] = 1; 13 } 14 for (i = 0; i < 1000; ++i) prim[i] = 1; 15 } 16 int getData(){ 17 int i, opt = 0; 18 for (i = 0; i < 4; ++i) opt = opt * 10 + data[i] - '0'; 19 return opt; 20 } 21 void setData(int a){ 22 for (int i = 3; ~i; --i) data[i] = '0' + a % 10, a /= 10; 23 } 24 int main(){ 25 rdy(); 26 int t,st, ed, now, nxt,i; 27 char j, tmp; 28 scanf("%d", &t); 29 while (t--){ 30 scanf("%d%d", &st, &ed); 31 memset(len, 0x7F, sizeof len); len[st] = 0; 32 std::queue<int> q; q.push(st); 33 while (!q.empty()){ 34 setData(now = q.front()); q.pop(); 35 for (i = 0; i < 4; ++i){ 36 tmp = data[i]; 37 for (j = '0'; j <= '9'; ++j){ 38 if (j == tmp) continue; 39 data[i] = j; nxt = getData(); 40 if (prim[nxt] || len[now] + 1 >= len[nxt]) continue; 41 len[nxt] = len[now] + 1; q.push(nxt); 42 } 43 data[i] = tmp; 44 } 45 } 46 printf("%d\n", len[ed]); 47 } 48 return 0; 49 }