CodeForces 734 D.Anton and Chess(map)

Description
一个棋盘上只有一个白子和n个黑子,黑子有三种:
B:可以走对角线,不能越过其他子
R:走直线,不能越过其他子
Q:可以走直线也可以走对角线,不能越过其他子
问这个白子是否会被某个黑子吃掉
Input
第一行一整数n表示黑子数量,之后两个整数x,y表示白子位置,最后n行每行输入一个黑子的类型和其位置(xi,yi) (1<=n<=5e5,-1e9<=x,y,xi,yi<=1e9)
Output
如果白子会被某个黑子吃掉则输出YES,否则输出NO
Sample Input
2
4 2
R 1 1
B 1 5
Sample Output
YES
Solution
先做一下坐标变换(xi,yi)->(xi-x,yi-y)把原点移到白子处,把所有点按距原点距离从小到大排序,从小到大判点,拿map存一下原点到该点的直线方向向量,对于当前判断的点,如果其斜率之前没有出现过,说明其与原点连线之间没有其他点阻挡,那么就根据其类型判断是否可以走到原点,如果可以则YES,否则将其斜率存map里
Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define INF 0x3f3f3f3f
#define maxn 555555
struct node
{
    int x,y,type;
    bool operator<(const node&b)const
    {
        ull t1=1ull*x*x+1ull*y*y;
        ull t2=1ull*b.x*b.x+1ull*b.y*b.y;
        return t1<t2;
    }
}a[maxn];
typedef pair<int,int>P;
map<P,int>m;
int n,xx,yy;
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
int main()
{
    while(~scanf("%d",&n))
    {
        scanf("%d%d",&xx,&yy);
        for(int i=1;i<=n;i++)
        {
            char op[3];
            scanf("%s%d%d",op,&a[i].x,&a[i].y);
            a[i].x-=xx,a[i].y-=yy;
            if(op[0]=='B')a[i].type=1;
            else if(op[0]=='R')a[i].type=2;
            else a[i].type=3;
        }
        sort(a+1,a+n+1);
        m.clear();
        int gg=1;
        for(int i=1;i<=n;i++)
        {
            int x=a[i].x,y=a[i].y,type=a[i].type;
            if(x==0)y/=abs(y);
            else if(y==0)x/=abs(x);
            else
            {
                int g=gcd(abs(x),abs(y));
                x/=g,y/=g;
            }
            if(type==1&&abs(x)==abs(y)||type==2&&(x==0||y==0)||type==3&&(abs(x)==abs(y)||x==0||y==0))
            {
                if(m.find(P(x,y))==m.end())
                {
                    gg=0;
                    break;
                }
            }
            m[P(x,y)]=1;
        }
        printf("%s\n",gg?"NO":"YES");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值