【NOIP2016提高A组模拟】小W学物理

来源:互联网 发布:上海企业seo外包 编辑:程序博客网 时间:2024/05/02 23:41

Description

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

Solution

排序之后,处理上下左右,然后直接模拟一下就好了。

Code

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=100007;typedef long long ll;ll i,j,k,t,n,m,x,y,h,fang,xx,yy,hh,tt,chu;int up[maxn],down[maxn],l[maxn],r[maxn],xa[maxn],ya[maxn],cc[maxn];bool bz[maxn][4],az;ll ans1,ans2,sum;char s[3];struct node{    int a,b,c,d;}a[maxn];bool cmp(node x,node y){    return x.a<y.a||x.a==y.a&&x.b<y.b;}bool cmp1(node x,node y){    return x.b<y.b||x.b==y.b&&x.a<y.a;}int main(){    freopen("mir.in","r",stdin);    freopen("mir.out","w",stdout);    scanf("%d%d%lld",&n,&m,&tt);x=0x7fffffff;    fo(i,1,n){        scanf("%d%d%s",&a[i].a,&a[i].b,s);        if(a[i].b==0&&a[i].a>0&&a[i].a<x)h=i,x=a[i].a;        if(s[0]=='/')a[i].c=1;            a[i].d=i;        xa[i]=a[i].a,ya[i]=a[i].b,cc[i]=a[i].c;    }    sort(a+1,a+1+n,cmp);    fo(i,2,n)if(a[i-1].a==a[i].a)up[a[i-1].d]=a[i].d,down[a[i].d]=a[i-1].d;    sort(a+1,a+1+n,cmp1);    fo(i,2,n)if(a[i-1].b==a[i].b)l[a[i].d]=a[i-1].d,r[a[i-1].d]=a[i].d;    chu=x;    fang=0;r[n+1]=h;h=n+1;x=y=0;    while(sum<tt){        if(bz[h][fang]&&!az){            k=(tt-chu)/(sum-chu);            while(k&&((sum-chu)*k+chu>tt))k--;            sum=chu+(sum-chu)*k;            az=1;        }        bz[h][fang]=1;        if(fang==0)hh=r[h];        if(fang==1)hh=up[h];        if(fang==2)hh=l[h];        if(fang==3)hh=down[h];        k=abs(xa[h]-xa[hh])+abs(ya[hh]-ya[h]);        if((!hh)||(sum+k>=tt)){            if(fang==0)x+=tt-sum;            if(fang==1)y+=tt-sum;            if(fang==2)x-=tt-sum;            if(fang==3)y-=tt-sum;             break;           }        sum+=k,x=xa[hh],y=ya[hh];h=hh;        t=cc[hh];        if(!t){            if(fang==1||fang==3)fang=(fang+1)%4;            else fang=(fang-1+4)%4;        }        else{            if(fang==0||fang==2)fang=(fang+1)%4;            else fang=(fang-1+4)%4;            }    }    printf("%lld %lld\n",x,y);}
2 0