杭电OJ第4255题,A Famous Grid(题目链接)。
A Famous Grid
Problem Description
Mr. B has recently discovered the grid named "spiral grid".
Construct the grid like the following figure. (The grid is actually infinite. The figure is only a small part of it.)
Considering traveling in it, you are free to any cell containing a composite number or 1, but traveling to any cell containing a prime number is disallowed. You can travel up, down, left or right, but not diagonally. Write a program to find the length of the shortest path between pairs of nonprime numbers, or report it's impossible.
Input
Each test case is described by a line of input containing two nonprime integer 1 ≤ x, y ≤ 10,000.
Output
For each test case, display its case number followed by the length of the shortest path or "impossible" (without quotes) in one line.
Sample Input
1 4
9 32
10 12
Sample Output
Case 1: 1
Case 2: 7
Case 3: impossible
Source
解题思路:广度优先搜索(BFS)。把相邻的遍历一遍。如果不是质数,则入队。我的队列用的是STL中的queue来实现的。
C++语言源代码如下:
#include <cstdio> #include <cstdlib> #include <cstring> #include <cassert> #include <queue> using namespace std; #define MAX_LENGTH 150 typedef int COUNT; typedef struct { int x, y; } Point; typedef enum { LEFT, RIGHT, UP, DOWN } DIRECTION; bool isPrime[MAX_LENGTH * MAX_LENGTH + 1]; inline void getprime (void) { COUNT i, j; const int max_number = MAX_LENGTH * MAX_LENGTH; memset( isPrime, true, sizeof(isPrime) ); isPrime[0] = false; isPrime[1] = false; for ( i = 2; i <= max_number ; i ++ ) { if ( isPrime[i] ) { for ( j = ( i << 1 ) ; j <= max_number ; j += i ) isPrime[j] = false; } } } void init_mat( int mat[MAX_LENGTH][MAX_LENGTH] ) { COUNT i, j, max_steps_count; DIRECTION direction; const int max_number = MAX_LENGTH * MAX_LENGTH; Point current_postition; memset( mat, 0, max_number * sizeof(int) ); if ( (MAX_LENGTH & 1) ) // odd number current_postition.x = current_postition.y = (MAX_LENGTH >> 1); else { current_postition.x = (MAX_LENGTH >> 1); current_postition.y = current_postition.x - 1; } max_steps_count = 1; j = 0; direction = RIGHT; for ( i = 1 ; i <= max_number ; i ++ ) { if ( isPrime[i] ) mat[current_postition.x][current_postition.y] = 0; else mat[current_postition.x][current_postition.y] = i; j ++; switch ( direction ) { case LEFT: current_postition.y --; break; case RIGHT: current_postition.y ++; break; case UP: current_postition.x --; break; case DOWN: current_postition.x ++; break; default: assert(false); } if ( j >= max_steps_count ) { j = 0; switch ( direction ) { case LEFT: direction = DOWN; break; case RIGHT: direction = UP; break; case UP: max_steps_count ++; direction = LEFT; break; case DOWN: max_steps_count ++; direction = RIGHT; break; default: assert(false); } } } } inline Point find_position( const int mat[MAX_LENGTH][MAX_LENGTH], const int number ) { Point result = {-1, -1}; COUNT i, j; for ( i = 0 ; i < MAX_LENGTH ; i ++ ) { for ( j = 0 ; j < MAX_LENGTH ; j ++ ) { if ( mat[i][j] == number ) { result.x = i; result.y = j; return result; } } } return result; } inline void visit( queue <Point> & Q, const int mat[MAX_LENGTH][MAX_LENGTH], int mat_step[MAX_LENGTH][MAX_LENGTH], const Point & position, const int step ) { if ( position.x < 0 ) return; if ( position.y < 0 ) return; if ( position.x >= MAX_LENGTH ) return; if ( position.y >= MAX_LENGTH ) return; if ( mat[position.x][position.y] != 0 ) { if ( mat_step[position.x][position.y] == -1 ) { mat_step[position.x][position.y] = step; Q.push(position); } else if ( step < mat_step[position.x][position.y] ) { mat_step[position.x][position.y] = step; Q.push(position); } } } int BFS( const int mat[MAX_LENGTH][MAX_LENGTH], const int start, const int end ) { static int mat_step[MAX_LENGTH][MAX_LENGTH]; Point current_postition, next_position, end_position; int current_step, next_step; queue <Point> Q; end_position = find_position( mat, end ); if ( end_position.x == -1 ) return -1; memset( mat_step, 0xff, sizeof( mat_step ) ); current_postition = find_position( mat, start ); Q.push( current_postition ); mat_step[current_postition.x][current_postition.y] = 0; while ( !Q.empty() ) { current_postition = Q.front(); Q.pop(); current_step = mat_step[current_postition.x][current_postition.y]; next_step = current_step + 1; // up next_position.x = current_postition.x - 1; next_position.y = current_postition.y; visit( Q, mat, mat_step, next_position, next_step ); // down next_position.x = current_postition.x + 1; next_position.y = current_postition.y; visit( Q, mat, mat_step, next_position, next_step ); // left next_position.x = current_postition.x; next_position.y = current_postition.y - 1; visit( Q, mat, mat_step, next_position, next_step ); // right next_position.x = current_postition.x; next_position.y = current_postition.y + 1; visit( Q, mat, mat_step, next_position, next_step ); } return mat_step[end_position.x][end_position.y]; } int main (void) { int test_case = 0; int start, end; int steps; static int mat[MAX_LENGTH][MAX_LENGTH]; getprime( ); init_mat( mat ); while ( scanf( "%d%d", &start, &end ) != EOF ) { test_case ++; steps = BFS( mat, start, end ); if ( steps < 0 ) printf( "Case %d: impossible\n", test_case ); else printf( "Case %d: %d\n", test_case, steps ); } return EXIT_SUCCESS; }