「6月雅礼集训 2017 Day8」route

【题目大意】

给出平面上$n$个点,求一条连接$n$个点的不相交的路径,使得转换的方向符合所给长度为$n-2$的字符串。

$n \leq 5000$

【题解】

考虑取凸包上一点,然后如果下一个是‘R',也就是向右转,那么就连到最左的点,这样下一次无论连到哪里都是向右;如果是'L',同理。

由于每次都是一个半平面,所以不会相交。

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

const int N = 1e5 + 10, M = 2e5 + 10;

int n;
struct P {
    int x, y;
    P() {}
    P(int x, int y) : x(x), y(y) {}
    friend P operator + (P a, P b) {
        return P(a.x+b.x, a.y+b.y);
    }
    friend P operator - (P a, P b) {
        return P(a.x-b.x, a.y-b.y);
    }
    friend ll operator * (P a, P b) {
        return - 1ll * a.y * b.x + 1ll * a.x * b.y;
    }
    friend ll operator / (P a, P b) {
        return 1ll * a.x * b.x + 1ll * a.y * b.y;
    }
    inline void set() {
        scanf("%d%d", &x, &y);
    }
}p[M];

int ans[M], an;
char str[M];
bool v[M];

int main() {
//    freopen("route.in", "r", stdin);
//    freopen("route.out", "w", stdout);
    cin >> n;
    for (int i=1; i<=n; ++i) p[i].set();
    int id = 1;
    for (int i=2; i<=n; ++i) if(p[i].x > p[id].x) id = i;
    ans[++an] = id; v[id] = 1;
    scanf("%s", str+1);
    for (int i=1; i<=n-2; ++i) {
        for (int j=1; j<=n; ++j)
            if(!v[j]) {
                id = j;
                break;
            }
        for (int j=id+1; j<=n; ++j) 
            if(!v[j]) {
                if(((p[id] - p[ans[i]]) * (p[j] - p[ans[i]]) > 0) ^ (str[i] == 'L')) id = j;
            }
        ans[++an] = id; v[id] = 1;
    }
    for (int i=1; i<=n; ++i) if(!v[i]) ans[++an] = i;
    for (int i=1; i<=n; ++i) printf("%d ", ans[i]);
    puts("");
    return 0;
}
View Code

 

posted @ 2017-06-24 20:14  Galaxies  阅读(233)  评论(0编辑  收藏  举报