ACM spiral grid

OpenSoucre發表於2014-04-26

spiral grid

時間限制:2000 ms  |  記憶體限制:65535 KB
難度:4
 
描述
Xiaod 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. In addition, traveling from a prime number is disallowed, either. 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.
 
輸入
Each test case is described by a line of input containing two nonprime integer 1 <=x, y<=10,000.
輸出
For each test case, display its case number followed by the length of the shortest path or "impossible" (without quotes) in one line.
樣例輸入
1 4
9 32
10 12
樣例輸出
Case 1: 1
Case 2: 7
Case 3: impossible

注意起點可以是素數,蛇形填數+廣度搜尋
本題用到的技巧
(1)注意蛇形填數,為grid加了一個邊框,邊框的值為-1,這樣生成數字時不用考慮是否越界,在廣度搜尋時也不用判斷是否越界
(2)利用pair<int,int>充當point不用再定義資料結構
(3)在廣度搜尋時,要確定每層是否已經遍歷完,每層遍歷完後將Point(0,0)壓入佇列中作為層與層的分隔
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <queue>
using namespace std;
typedef pair<int,int> Point;
int grid[102][102]={0};
const int dx[] = {0,1,0,-1};      //右,下,左,上
const int dy[] = {1,0,-1,0};
void make_spiral_grid(){
    for(int i = 0 ;i < 102; ++ i) grid[0][i]=grid[i][0]=grid[101][i]=grid[i][101]= -1;
    int number =100*100,x = 1,y = 0,step = 0;
    while(number){
        step%=4;
        while(grid[x+dx[step]][y+dy[step]] == 0){
            x+=dx[step];y+=dy[step];
            grid[x][y]=number--;
        }
        step++;
    }
}

bool isPrime(int n){
    if(n < 0) return true;
    if(n == 1) return false;
    if(n%2 == 0) return (n==2);
    if(n%3 == 0) return (n==3);
    if(n%5 == 0) return (n==5);
    for(int i = 7; i*i <= n; i+=2 ){
        if(n%i == 0) return false;
    }
    return true;
}

Point getPointFromGrid(int v){
    for(int i = 1; i <= 100; i++){
        for(int j = 1; j <= 100; j++){
            if(grid[i][j] == v) return Point(i,j);
        }
    }
    return Point(0,0);
}

int bfs(int startV,int endV){
    vector<vector<bool> > visit(102,vector<bool>(102,false));
    Point startPoint = getPointFromGrid(startV);
    queue<Point> points;
    points.push(startPoint);
    visit[startPoint.first][startPoint.second] = true;
    points.push(Point(0,0));
    int step = 1;
    while(!points.empty()){
        Point a = points.front(); points.pop();
        if(a.first == 0 && a.second == 0) {
             if(points.empty()) break;
             points.push(a);
             step++;
             continue;
        }
        for(int i = 0 ; i < 4; ++ i){
            int newx = a.first  + dx[i];
            int newy = a.second + dy[i];
            if(grid[newx][newy]==endV) return step;
            if(!isPrime(grid[newx][newy]) && !visit[newx][newy]) {
                points.push(Point(newx,newy));
                visit[newx][newy] = true;
            }
        }
    }
    return 0;
}

int main(){
    make_spiral_grid();
    int icase = 0,x,y;
    while(cin >> x >> y){
        if(isPrime(y)) cout<<"Case "<<++icase<<": impossible"<<endl;
        else if(x == y ) cout<<"Case "<<++icase<<": 0"<<endl;
        else{
            int res = bfs(x,y);
            if(res == 0) cout<<"Case "<<++icase<<": impossible"<<endl;
            else cout<<"Case "<<++icase<<": "<<res<<endl;
        }
    }
}