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;
}