JZOJ 4823. 【NOIP2016提高A组集训第1场10.29】小W学物理

题目

Description

为了测试小W的物理水平,Mr.X在二维坐标系中放了N面镜子(镜子坐标绝对值不超过M),镜子均与坐标轴成45°角,所以一共有两种类型“/”和“\”。原点不会有镜子,任意一点最多只有一面镜子。
镜子两个面都能反光,而中间不透光,例如,对于一个“/”型镜子,下方向射入的光线会被反射到右方向,左方向射入的光线会被反射到上方向。
现在有一条光线从原点沿X轴正方向射出,求走过T路程后所在位置。

Input

第一行三个整数N,M,T。
第2到N+1行,每行两个整数Xi,Yi,表示镜子坐标,一个字符Si表示镜子类型

Output

一行两个整数,表示走过T路程后的坐标。

Sample Input

5 2 8
0 1 \
0 2 /
1 0 /
1 1 \
1 2 \

Sample Output

3 1

Data Constraint

对于10%的数据:N=1
对于25%的数据:T<=1000000
对于35%的数据:N<=1000
对于60%的数据:M<=1000
对于100%的数据:N<=100,000,M<=1,000,000,000,T<=10^18

Solution

我们不用怕,直接纯模拟。
我们按照横纵坐标分别排序,然后就可以得出当前镜子将会到达哪个镜子。
有点恶心,不过沉稳地打完,仔细改改就好。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define N 100010
#define LL long long
using namespace std;
const LL fx[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
struct note
{
    LL x,y,w,r;
};
note a[N],b[N];
LL i,j,n,m,t,rm,x,y,z,xb,o,mn,c[N];
char ch;
bool cmpy(note a,note b)
{
    if (a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}
bool cmpx(note a,note b)
{
    if (a.y==b.y) return a.x<b.x;
    return a.y<b.y;
}
int main()
{
    freopen("mir.in","r",stdin);
    freopen("mir.out","w",stdout);
    scanf("%lld%lld%lld",&n,&m,&t);
    mn=10000000001;
    fo(i,1,n)
    {
        scanf("%lld%lld %c\n",&x,&y,&ch);
        a[i].x=x;
        a[i].y=y;
        if (ch=='/') a[i].r=1;
        if (y==0)
        {
            o=1;
            if (x>0) mn=min(mn,x);
        }
    }
    a[0].x=a[0].y=1000000001;
    sort(a+1,a+n+1,cmpx);
    fo(i,1,n) a[i].w=i;
    memcpy(b,a,sizeof(b));
    sort(b+1,b+n+1,cmpy);
    fo(i,1,n) c[b[i].w]=i;
    if (!o)
    {
        printf("%lld %lld",t,0);
        return 0;
    }
    if (t<=mn)
    {
        printf("%lld %lld",t,0);
        return 0;
    }
    fo(i,1,n)
        if (a[i].x==mn && a[i].y==0)
        {
            xb=i;
            break;
        }
    x=a[xb].x;y=a[xb].y;rm=t-a[xb].x;
    if (a[xb].r==1) z=1;else z=3;
    while (rm)
    {
        if (z%2)
        {
            xb=c[xb];
            if (z==1)
            {
                if (b[xb+1].x==b[xb].x)
                {
                    if (rm<=b[xb+1].y-b[xb].y)
                    {
                        printf("%lld %lld",b[xb].x,b[xb].y+rm);
                        return 0;
                    }
                    rm-=b[xb+1].y-b[xb].y;
                    xb++;
                    if (b[xb].r==1) z=0;else z=2;
                    xb=b[xb].w;
                } else
                {
                    printf("%lld %lld",b[xb].x,b[xb].y+rm);
                    return 0;
                }
            }
            if (z==3)
            {
                if (b[xb-1].x==b[xb].x)
                {
                    if (rm<=b[xb].y-b[xb-1].y)
                    {
                        printf("%lld %lld",b[xb].x,b[xb].y-rm);
                        return 0;
                    }
                    rm-=b[xb].y-b[xb-1].y;
                    xb--;
                    if (b[xb].r==1) z=2;else z=0;
                    xb=b[xb].w;
                } else
                {
                    printf("%lld %lld",b[xb].x,b[xb].y-rm);
                    return 0;
                }
            }
        } else
        if (z==0 || z==2)
        {
            if (z==0)
            {
                if (a[xb+1].y==a[xb].y)
                {
                    if (rm<=a[xb+1].x-a[xb].x)
                    {
                        printf("%lld %lld",a[xb].x+rm,a[xb].y);
                        return 0;
                    }
                    rm-=a[xb+1].x-a[xb].x;
                    xb++;
                    if (a[xb].r==1) z=1;else z=3;
                } else
                {
                    printf("%lld %lld",a[xb].x+rm,a[xb].y);
                    return 0;
                }
            }
            if (z==2)
            {
                if (a[xb-1].y==a[xb].y)
                {
                    if (rm<=a[xb].x-a[xb-1].x)
                    {
                        printf("%lld %lld",a[xb].x-rm,a[xb].y);
                        return 0;
                    }
                    rm-=a[xb].x-a[xb-1].x;
                    xb--;
                    if (a[xb].r==1) z=3;else z=1;
                } else
                {
                    printf("%lld %lld",a[xb].x-rm,a[xb].y);
                    return 0;
                }
            }
        }
    }
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值