1. 程式人生 > >弱校聯萌十一大決戰之強力熱身 J. Right turn (模擬)

弱校聯萌十一大決戰之強力熱身 J. Right turn (模擬)

J. Right turn
Time Limit: 1000msMemory Limit: 65536KB 64-bit integer IO format: %lld Java class name: Main
Submit Status
frog is trapped in a maze. The maze is infinitely large and divided into grids. It also consists of n obstacles, where the i-th obstacle lies in grid (xi,yi).

frog is initially in grid (0,0), heading grid (1,0). She moves according to The Law of Right Turn: she keeps moving forward, and turns right encountering a obstacle.

The maze is so large that frog has no chance to escape. Help her find out the number of turns she will make.
Input
The input consists of multiple tests. For each test:

The first line contains 1 integer n (0≤n≤103). Each of the following n lines contains 2 integers xi,yi. (|xi|,|yi|≤109,(xi,yi)≠(0,0), all (xi,yi) are distinct)
Output
For each test, write 1 integer which denotes the number of turns, or ‘‘-1′′ if she makes infinite turns.
Sample Input
2
1 0
0 -1
1
0 1
4
1 0
0 1
0 -1
-1 0
Sample Output
2
0
-1

解析:碰到一個障礙物就右轉彎,沿著四個方向一層一層不斷向外擴充套件,大致形狀像一個折線構成的阿基米德螺線,時刻記住,在當前方向向外擴充套件,並且擴充套件的點距當前點最近就行了,詳見程式碼

AC程式碼:

#include <bits/stdc++.h>
using namespace std;

int n;
struct Node{    //點
    int x, y, dir;
}current;
vector<Node> visited;
map<int, set<int> > _x, _y;

bool operator == (Node a, Node b){    //定義點相等
    return a.x == b.x && a.y == b.y && a.dir == b.dir;
}

bool move(){
    int x = current.x, y = current.y;
    set<int>::iterator it;
    if(current.dir == 0){    //x軸正方向
        it = _y[y].upper_bound(x);    //找縱座標相等且橫座標比當前點大且距離最小的點
        if(it != _y[y].end()){
            current.x = *it - 1;
            current.dir = 1;    //右轉
            return true;
        }
    }
    if(current.dir == 1){    //y軸負方向
        it = _x[x].lower_bound(y);    //找橫座標相等且縱座標比當前點小且距離最近的點
        if(it != _x[x].begin()) it --;
        if(it != _x[x].end() && *it < current.y){
            current.y = *it + 1;
            current.dir = 2;    //右轉
            return true;
        }
    }
    if(current.dir == 2){    //x軸負方向
        it = _y[y].lower_bound(x);    //找縱座標相等且橫座標比當前點小且距離最小的點
        if(it != _y[y].begin()) it --;
        if(it != _y[y].end() && *it < current.x){
            current.x = *it + 1;
            current.dir = 3;    //右轉
            return true;
        }
    }
    if(current.dir == 3){    //y軸正方向
        it = _x[x].upper_bound(y);    //找橫座標相等且縱座標比當前點大且距離最小的點
        if(it != _x[x].end()){
            current.y = *it - 1;
            current.dir = 0;    //右轉
            return true;
        }
    }
    return false;
}

bool is_circle(){    //判斷是否出現環
    int len = visited.size();
    for(int i=0; i<len; i++)
        if(visited[i] == current) return true;
    return false;
}

int main(){
    #ifdef sxk
        freopen("in.txt", "r", stdin);
    #endif // sxk

    int x, y;
    while(scanf("%d", &n) == 1){
        _x.clear();
        _y.clear();
        visited.clear();
        for(int i=0; i<n; i++){
            scanf("%d%d", &x, &y);
            _x[x].insert(y);
            _y[y].insert(x);
        }
        current.x = current.y = current.dir = 0;
        for(int i=0; ; i++){
            visited.push_back(current);
            if(!move()){
                printf("%d\n", i);
                break;
            }
            if(is_circle()){
                puts("-1");
                break;
            }
        }
    }
    return 0;
}