zoukankan      html  css  js  c++  java
  • 【原】 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: }

    如果您满意我的博客,请点击“订阅Allen Sun的技术博客”即可订阅,谢谢:)

    原创文章属于Allen Sun
    欢迎转载,但请注明文章作者Allen Sun和链接
  • 相关阅读:
    ABS(引数と同じ大きさの正の数を返す)
    WRITE
    LEAVE TO LIST-PROCESSING
    SHIFT(文字列の指定位置数の移動)
    【EXCEL】SUMIF(条件を指定して数値を合計する)
    【EXCEL】SUMIFS(複数の条件を指定して数値を合計する)
    【財務会計】流動資産と固定資産の違いとは?ディズニーを例にわかりやすく解説
    【財務会計】償却 とは
    【財務会計】固定資産の除却と廃棄の違い
    尽力去做你力所能及的事
  • 原文地址:https://www.cnblogs.com/allensun/p/1872052.html
Copyright © 2011-2022 走看看