杭电OJ第4255题 A Famous Grid

  杭电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.)

杭电OJ第4255题 A Famous Grid_第1张图片

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.

杭电OJ第4255题 A Famous Grid_第2张图片

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

Fudan Local Programming Contest 2012

  解题思路:广度优先搜索(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;
}

你可能感兴趣的:(杭电OJ第4255题 A Famous Grid)