POJ 3126 Prime Path(BFS求“最短路”)

题意:给出两个四位数的素数,按如下规则变换,使得将第一位数变换成第二位数的花费最少,输出最少值,否则输出0。      

  每次只能变换四位数的其中一位数,使得变换后的数也为素数,每次变换都需要1英镑(即使换上的数是以前被换下的)。

思路:若素数a可以按上述规则转化为b,则可以看做a、b直接有一条边。显然,从初始值到目标值的路径上的边数即为花费的      

   数目,这样一来,就相当于求最短路径。由于题目只要求最小花费数,所以不需要存储有向图。      

  用BFS搜索,每次枚举当前值x所能变换得到的值y,若y满足条件,将y以及从初始值达到当前y值所需要的次数压入队列。      

  只要当从队列取出的数值等于目标值,此时的花费即为答案,结束循环。

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>

using namespace std;

int start,goal,t;//start:初始值,goal:目标值
int prime[10001];
int vis[10001];//标记数i是否之前已经被转换过

struct Node{
    int num;
    int step; //从start变为num所需要的步数
};

//将x的第i位的值改成j
int change(int x,int i,int j){
    if(i==1)
        return x-x%10+j;
    if(i==2)
        return (x/100)*100+x%10+j*10;
    if(i==3)
        return (x/1000)*1000+x%100+j*100;
    if(i==4)
        return x%1000+j*1000;
    return 0;
}


int bfs(int start,int ends){
    queue<Node> q;
    Node a,b;
    vis[start]=1;
    a.num=start;
    a.step=0;
    q.push(a);
    while(!q.empty()){
        a=q.front();
        q.pop();
        //只要a.num等于目标值的话,就退出循环。
        //因为不可能有比这花费最少的情况了。
        if(a.num==ends){
            return a.step;
        }
        vis[a.num]=1;
        //枚举
        for(int i=1;i<=4;i++){
            for(int j=0;j<=9;j++){
                //若为偶数,直接继续
                if(i==1 && j%2==0)
                    continue;
                if(i==4&&j==0)
                    continue;
                int temp=change(a.num,i,j);
                if(prime[temp]==0 || vis[temp])
                    continue;
                b.num=temp;
                b.step=a.step+1;
                q.push(b);
            }
        }

    }
    return -1;
}
//预处理1000~9999的素数
void dealWithPrime(){
    memset(prime,1,sizeof(prime));
    for(int i=2;i<10000;i++){
        if(prime[i]){
            for(int j=i*i;j<10000;j+=i){
                prime[j]=0;
            }
        }
    }
}

int main()
{
    dealWithPrime();
    scanf("%d",&t);
    for(int i=1;i<=t;i++){
        scanf("%d%d",&start,&goal);
        memset(vis,0,sizeof(vis));
        int ans=bfs(start,goal);
        if(ans==-1)
            printf("0\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2013-10-11 20:30  辰曦~文若  阅读(255)  评论(0编辑  收藏  举报