0
点赞
收藏
分享

微信扫一扫

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


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


举报

相关推荐

0 条评论