Codeforces 1158D/1159F - Winding polygonal line (几何)

Codeforces Round #559 (Div. 1) D. Winding polygonal line

Codeforces Round #559 (Div. 2) F. Winding polygonal line


题意

给定\(n\)个点及一串长度为\(n-2\)的字符串,字符串仅为\(L\)\(R\)两种字符组成

使给定\(n\)个点的一种排列,使得在坐标系中将这种排列连接成有向图后,线的拐角符合给定的字符串

不存在两个以上的点共存于一条线上(即一定有解)


限制

\(3\le n\le 2000\)

\(-10^9\le x_i,y_i\le 10^9\)




思路

初始时在凸包上任意选择一个点作为起点均可(这里选择\(x\)坐标最小的点)

然后执行\(n-2\)次循环

如果对应的方向为\(L\)(向左),那么就是在剩余的点的凸包上选择一个最右边的点,就能够保证接下来不论走向哪个没走过的点,它的拐角都会是\(L\)

同理,如果对应的方向为\(R\)(向右),那么就是在剩余的点的凸包上选择一个最左边的点

这部分通过向量叉乘的正负值判断,使用\(id\)标记选中的最后一个点,使用\(nxt\)储存可能选择的下一个点,\(j\)变量循环剩余的没有使用过的点

如果两个向量\(id\rightarrow nxt\)\(nxt\rightarrow j\)的值小于\(0\),则表示\(j\)点比当前的\(nxt\)点更靠右

如果两个向量\(id\rightarrow nxt\)\(nxt\rightarrow j\)的值大于\(0\),则表示\(j\)点比当前的\(nxt\)点更靠左

故时间复杂度为\(O(n^2)\)




程序

(62ms/1000ms)

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define pb push_back
#define eb emplace_back
#define mst(a,b) memset(a,b,sizeof(a))
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const double angcst=PI/180.0;
const ll mod=998244353;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}

struct vect
{
    ll x,y;
    double crossProd(vect v)
    {
        return x*v.y-y*v.x;
    }
};

struct point
{
    ll x,y;
    bool vis;
}ar[2050];

char str[2050];

void solve()
{
    int n;
    cin>>n;
    ll minx=LINF;
    int id=1;
    rep(i,1,n)
    {
        cin>>ar[i].x>>ar[i].y;
        if(ar[i].x<minx)
        {
            minx=ar[i].x;
            id=i;
        }
        ar[i].vis=false;
    }
    
    cin>>str+2;
    
    cout<<id;
    ar[id].vis=true;
    
    repp(i,2,n)
    {
        int nxt=1;
        rep(j,1,n)
            if(!ar[j].vis)
            {
                nxt=j;
                break;
            }
        vect vec=vect{ar[nxt].x-ar[id].x,ar[nxt].y-ar[id].y};
        if(str[i]=='L')
        {
            rep(j,nxt+1,n)
            {
                if(ar[j].vis)
                    continue;
                if(vec.crossProd(vect{ar[j].x-ar[nxt].x,ar[j].y-ar[nxt].y})<0)
                {
                    nxt=j;
                    vec=vect{ar[nxt].x-ar[id].x,ar[nxt].y-ar[id].y};
                }
            }
        }
        else
        {
            rep(j,nxt+1,n)
            {
                if(ar[j].vis)
                    continue;
                if(vec.crossProd(vect{ar[j].x-ar[nxt].x,ar[j].y-ar[nxt].y})>0)
                {
                    nxt=j;
                    vec=vect{ar[nxt].x-ar[id].x,ar[nxt].y-ar[id].y};
                }
            }
        }
        id=nxt;
        ar[id].vis=true;
        cout<<' '<<id;
    }
    
    rep(i,1,n)
    {
        if(!ar[i].vis)
        {
            cout<<' '<<i<<'\n';
            return;
        }
    }
}
int main()
{
    closeSync;
    //multiCase
    {
        solve();
    }
    return 0;
}

posted @ 2020-12-20 12:04  StelaYuri  阅读(122)  评论(0编辑  收藏  举报