Arena Olympics(Gym-102267F)

Problem Description

Kassandra is participating in the Arena Olympics of Sparta. In order to win the arena fight, she has to knockout all the other N fighters.

Being a computer scientist, she wanted to do it while preserving her energy as much as possible, so she wants to win the fight without being noticed by any of the other fighters. To be more exact, she knows the position of each other fighter in the arena, the angle of the center of his field of view, and the range of his field of view.

If she knocks a fighter out while she's in the field of view of another fighter, she will be noticed and she would have to fight everyone face on. So she wonders if there exists an order of fighters to knockout such that no one notices her during the whole process.

Print any permutation such that if she knocks-out the fighters in this order, she won't be noticed. Or print −1 if there exists no such permutation.

Note that Kassandra can move freely while not knocking someone out to get to the position of any other fighter.

Input

The first line of the input will contain an integer N(1≤N≤3000).

Each of the following lines will contain 4 integers each: xi, yi, ai, ri (−106≤xi,yi≤106,0≤ai≤359,0≤ri≤89) - the x coordinate, y coordinate, the angle of the center of the field of view, and the range of the field of view of the ithith fighter respectively. No two fighters share the same position.

Output

If there exists such a permutation, print the order of the ids of the N participants on a single line separated by a space. Otherwise, print −1.

Examples

Input

4
-2 1 35 25
-3 -2 35 25
0 -3 110 25
2 1 245 25

Output

2 4 3 1

Input

2
-3 -3 45 45
3 3 225 45

Output

-1

Note

The field of view ranges from the angle a−ra−r to the angle a+ra+r.

Below is the illustration of the first case:

题意:给出 n 个点的坐标 (x,y) 以及两个与每个点有关的视野参数 a、人,问能否在不被其他点的视野发现的情况下,按顺序消除每个点,若能,输出消除顺序,若不能输出 -1

思路:

题目本质是根据点之间能否看到的关系建立有向边,然后跑拓扑排序输出拓扑顺序,因此关键问题就是根据 a、r 来判断点之间的可见关系

对于第 i 个点,根据参数 r、a 可计算出其视野角度范围 L[i]、R[i],然后枚举其他的点

对于第 j 个点,首先从第 i 个点向第 j 个点做平行于 x 轴的直线 AB,然后从第 j 个点向直线做垂线 BC,再将第 j 个点连接到第 i 个点做一条直线 CA,从而得到一个三角形 ABC,然后判断 ∠CAB 是否在视野范围内即可

设第 i 个点坐标为 (xi,yi),第 j 个点坐标为 (xj,yj),∠CAB 为 zeta,根据平面几何的知识,有:AB=xj-xi,BC=yj-yi,zeta=arctan(BC/AB)

由于 zeta 算出来后是弧度,因此需要转成角度 zeta 再进行比较,即对 zeta 乘以 180 除以 PI 即可

得到角度 zeta 后,比较其与 L[i]、R[i] 的大小,即可知道点 j 是否在点 i 的视野范围内,若在 j 在 i 视野范围内,就建一条从 i 到 j 的边,表示只有先消除点 i 才能消除点 j

当建完所有边后,跑拓扑排序即可

Source Program

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<int,int>
const int MOD = 1E9+7;
const int N = 5000+5;
const int dx[] = {1,-1,0,0,-1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;

int x[N],y[N];
int L[N],R[N];
int G[N][N];
int in[N];
int main() {
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int r,a;
        scanf("%d%d%d%d",&x[i],&y[i],&a,&r);
        L[i]=((a-r)+360)%360;
        R[i]=(a+r)%360;
    }

    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j)
                continue;

            int dx=x[j]-x[i];
            int dy=y[j]-y[i];
            double zeta=atan2(dy,dx);
            if(zeta<0)
                zeta+=2*PI;
            zeta=zeta*180/PI;

            if(L[i]>R[i]){
                if(zeta-EPS<=R[i]||zeta+EPS>=L[i]){
                    G[i][j]=1;
                    in[j]++;
                }
            }
            else{
                if(zeta+EPS>=L[i]&&zeta-EPS<=R[i]){
                    G[i][j]=1;
                    in[j]++;
                }
            }
        }
    }

    queue<int> Q;
    for(int i=1;i<=n;i++)
        if(in[i]==0)
            Q.push(i);

    vector<int> V;
    while(!Q.empty()){
        int x=Q.front();
        Q.pop();
        V.push_back(x);

        for(int i=1;i<=n;i++){
            if(G[x][i]==1&&in[i]>0){
                in[i]--;
                if(in[i]==0)
                    Q.push(i);
            }
        }
    }

    if(V.size()<n)
        printf("-1\n");
    else{
        for(int i=0;i<V.size();i++)
            printf("%d ",V[i]);
        printf("\n");
    }

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值