您的位置:首页 > 其它

POJ 3126 Prime Path (构造 + BFS)

2015-02-10 09:42 471 查看
Prime Path

Time Limit: 1000MSMemory Limit: 65536K
Total Submissions: 11991Accepted: 6809
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

Source
Northwestern Europe 2006

题目链接:http://poj.org/problem?id=3126

题目大意:输入两个四位素数,求从第一个变换到第二的最小变换步数,每次只能更改四位里一位的值并且要求更改后的数字仍然是素数。

题目分析:BFS,像这类求最短的搜索通常都是BFS,从第一个数字开始,每位拆分,凡是符合条件的素数进队列,这里判素数需要一个素数筛,

我们不需要考虑怎样得到最短的步数,因为采用广度优先搜索出来的解必定最短。拆数字的时候记得还原,举个例子,比如1033是个素数,拆十位

的时候10x3 (0 <= x <= 9)这时候若找不到可以进队列的值,要将其还原成1033,本题有一点很重要,我做的时候忽略掉了,就是怎么变换数字都

要求是4位的,因此在拆千位的时候是从1-9而不是0-9!

这题代码写的相当丑。。。

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int st, ed;
int prime[1000001];
bool used[1000001];

struct NUM
{
    int num;
    int step;
};

void get_prime()  //素数筛
{ 
    memset(prime, 1, sizeof(prime));  
    prime[1] = 0;  
    for(int i = 2; i <= 1000; i++)    
        if(prime[i])    
            for(int j = i * i; j <= 1000000; j += i)    
                prime[j] = 0;  
}

int BFS()
{
    memset(used, false, sizeof(used));
    queue<NUM> q;
    NUM s, tmp, cur;
    s.num = st;
    s.step = 0;
    used[st] = true;
    q.push(s);
    while(!q.empty())
    {
        cur = q.front();
        q.pop();
        if(cur.num == ed)
            return cur.step;
        tmp = cur;
        tmp.num -= (tmp.num % 10);
        for(int i = 0; i < 10; i++) //拆个位
        {
            tmp.num += i;
            tmp.step++;
            if(tmp.num == ed)
                return tmp.step;
            //若该数字没使用过且是个素数则标记为已使用并进队列
            if(!used[tmp.num] && prime[tmp.num])
            {
                used[tmp.num] = true;
                q.push(tmp);
            }
            tmp.num -= i;   //还原
            tmp.step--;
        }
        tmp = cur;
        tmp.num -= (((tmp.num / 10) % 10) * 10);
        for(int i = 0; i < 10; i++) ////拆十位
        {
            tmp.num += (i * 10);
            tmp.step++;
            if(tmp.num == ed)
                return tmp.step;
            if(!used[tmp.num] && prime[tmp.num])
            {
                used[tmp.num] = true;
                q.push(tmp);
            }
            tmp.num -= (i * 10);
            tmp.step--;
        }
        tmp = cur;
        tmp.num -= (((tmp.num / 100) % 10) * 100);
        for(int i = 0; i < 10; i++) //拆百位
        {
            tmp.num += (i * 100);
            tmp.step++;
            if(tmp.num == ed)
                return tmp.step;
            if(!used[tmp.num] && prime[tmp.num])
            {
                used[tmp.num] = true;
                q.push(tmp);
            }
            tmp.num -= (i * 100);
            tmp.step--;
        }
        tmp = cur;
        tmp.num -= ((tmp.num / 1000) * 1000);
        for(int i = 1; i < 10; i++) //拆千位
        //!!!千位的第一位不能是0!
        {
            tmp.num += (i * 1000);
            tmp.step++;
            if(tmp.num == ed)
                return tmp.step;
            if(!used[tmp.num] && prime[tmp.num])
            {
                used[tmp.num] = true;
                q.push(tmp);
            }
            tmp.num -= (i * 1000);
            tmp.step--;
        }
    }
    return -1;
}

int main()
{
    int n, ans;
    scanf("%d", &n);
    get_prime();
    while(n --)
    {
        scanf("%d %d", &st, &ed);
        ans = BFS();
        if(ans == -1)
            printf("Impossible\n");
        else
            printf("%d\n", ans);
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: