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和链接
  • 相关阅读:
    UVA 11174 Stand in a Line,UVA 1436 Counting heaps —— (组合数的好题)
    UVA 1393 Highways,UVA 12075 Counting Triangles —— (组合数,dp)
    【Same Tree】cpp
    【Recover Binary Search Tree】cpp
    【Binary Tree Zigzag Level Order Traversal】cpp
    【Binary Tree Level Order Traversal II 】cpp
    【Binary Tree Level Order Traversal】cpp
    【Binary Tree Post order Traversal】cpp
    【Binary Tree Inorder Traversal】cpp
    【Binary Tree Preorder Traversal】cpp
  • 原文地址:https://www.cnblogs.com/allensun/p/1872052.html
Copyright © 2011-2022 走看看