【原】 POJ 3126 Prime Path 筛素数+BFS单源无权最短路径 解题报告

 

http://poj.org/problem?id=3126


方法:
先筛出1000~9999的所有素数,对于其中每个素数求得他在图中的邻接点。其邻接点就是所有与其有一位不同的素数。
再用BFS搜索图找到指定源节点和目标节点之间的最短路径。若不联通则输出失败

 

Description

clip_image001The 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

 

   1: #include <stdio.h>
   2: #include <iostream>
   3: #include <vector>
   4:  
   5: using namespace std ;
   6:  
   7: //1000~9999
   8: const int N = 10000 ;
   9: const int INF = 0x7fffffff ;
  10:  
  11: struct slot
  12: {
  13:     slot():isPrime(1){}  //1表示素数,0表示合数
  14:     int isPrime ;
  15:     vector<int> adjList ;
  16: };
  17:  
  18: typedef vector< struct slot > Graph ;
  19:  
  20: Graph G ;
  21: int myQueue[N] ;  //自己写队列
  22:  
  23: //n*lglgn
  24: void GetPrimeTable()
  25: {
  26:     __int64 i, j ;  //必须用__int64,不然j=i*i会超出范围
  27:  
  28:     G.resize(N) ;
  29:     G[0].isPrime = G[1].isPrime= 0 ;
  30:     i = 2 ;
  31:     while( i<N )
  32:     {
  33:         for( j=i*i ; j<N ; j+=i )
  34:             G[j].isPrime = 0 ;
  35:         do ++i ;
  36:         while( i<N && G[i].isPrime==0 ) ;
  37:     }
  38: }
  39:  
  40: void GetAdjacentList()
  41: {
  42:     int i,j,k,t ;
  43:     int digit[4] ;
  44:     int partnum[4] ;
  45:     int prime,tmpnum ;
  46:  
  47:     for( i=1000 ; i<N ; ++i )
  48:     {
  49:         if( G[i].isPrime==0 )
  50:             continue ;
  51:  
  52:         prime = tmpnum = i ;
  53:         //得到每位数字放入digit[]
  54:         for( j=1000,k=0 ; j>=1 ; j/=10,++k )
  55:         {
  56:             digit[k] = tmpnum/j ;
  57:             tmpnum = tmpnum-digit[k]*j ;  //tmp%=j
  58:         }
  59:  
  60:         //得到除去某位的其他各位组成的数
  61:         partnum[0] = digit[1]*100+digit[2]*10+digit[3] ;
  62:         partnum[1] = digit[0]*1000+digit[2]*10+digit[3] ;
  63:         partnum[2] = digit[0]*1000+digit[1]*100+digit[3] ;
  64:         partnum[3] = digit[0]*1000+digit[1]*100+digit[2]*10 ;
  65:  
  66:         //枚举得到邻接表
  67:         for( j=1 ; j<=9 ; ++j )
  68:         {
  69:             tmpnum = j*1000 + partnum[0] ;
  70:             if( G[tmpnum].isPrime==1 && tmpnum != prime )
  71:                 G[prime].adjList.push_back(tmpnum) ;
  72:  
  73:         }
  74:         for( j=1,t=100 ; j<4 ; ++j,t/=10 )
  75:         {
  76:             for( k=0 ; k<=9 ; ++k )
  77:             {
  78:                 tmpnum = k*t + partnum[j] ;
  79:                 if( G[tmpnum].isPrime==1 && tmpnum != prime )
  80:                     G[prime].adjList.push_back(tmpnum) ;
  81:  
  82:             }
  83:         }
  84:     }
  85: }
  86:  
  87: void run3216()
  88: {
  89:     int n ;
  90:     int s,t ;
  91:     bool found ;
  92:     int curDist ;
  93:     int vertex,adjVertex ;
  94:     int front,rear,size ;
  95:     vector<int>::iterator vIter ;
  96:  
  97:     GetPrimeTable() ;
  98:     GetAdjacentList() ;
  99:  
 100:     scanf("%d", &n) ;
 101:     while( n-- )
 102:     {
 103:         found = false ;
 104:         vector<int> table(N,INF) ; //记录最短距离的table
 105:  
 106:         scanf("%d%d", &s,&t) ;
 107:  
 108:         size = 0 ;
 109:         rear = 0 ;
 110:         front = 1 ;
 111:  
 112:         table[s] = 0 ;  //起始点最短路径为0
 113:         myQueue[++rear] = s ;  //将起始点入队
 114:         ++size ;
 115:         while( size!=0 && !found )
 116:         {
 117:             vertex = myQueue[front++] ; //出队
 118:             --size ;
 119:             curDist = table[vertex] ;   //当前最短路径
 120:  
 121:             if( vertex == t )  //搜索到目标节点
 122:             {
 123:                 printf("%d\n", curDist) ;
 124:                 found = true ;
 125:                 break ;
 126:             }
 127:  
 128:             //将邻接点入队
 129:             for( vIter=G[vertex].adjList.begin() ; vIter!=G[vertex].adjList.end() ; ++vIter )
 130:             {
 131:                 adjVertex = *vIter ;
 132:                 if( table[adjVertex]==INF )  //未处理过的
 133:                 {
 134:                     table[adjVertex] = curDist+1 ;
 135:                     if( adjVertex == t )   //搜索到目标节点
 136:                     {
 137:                         printf("%d\n", curDist+1) ;
 138:                         found = true ;
 139:                         break ;
 140:                     }
 141:  
 142:                     myQueue[++rear] = adjVertex ;  //入队
 143:                     ++size ;
 144:                 }
 145:             }
 146:         }
 147:         if( !found )
 148:             printf( "Impossible" ) ;
 149:     }
 150: }
posted @ 2010-11-08 19:38  Allen Sun  阅读(402)  评论(0编辑  收藏  举报