您的位置:首页 > 其它

NOIP2016提高A组集训第1场【JZOJ4823】小W学物理

2016-10-29 16:40 477 查看

Description

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

Solution

我们判断一面镜子的上下左右分别是哪面镜子,然后模拟的跑一下,注意判一下环和是否已经永远遇不到镜子即可。

代码

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=100005;
struct code{
int a,b,d;
}a[maxn];
ll x[maxn],y[maxn],c[maxn],l[maxn],r[maxn],u[maxn],d[maxn];
ll n,m,s,t,i,j,k,sum,xx,yy,l1,bz[maxn][4],p;
char ch[10];
bool bz1;
bool cmp(code x,code y){
return x.a<y.a || x.a==y.a && x.b<y.b;
}
int main(){
freopen("mir.in","r",stdin);freopen("mir.out","w",stdout);
scanf("%lld%lld%lld",&n,&m,&s);
for (i=1;i<=n;i++){
scanf("%lld%lld%s",&x[i],&y[i],&ch),a[i].a=x[i],a[i].b=y[i],a[i].d=i;
if (ch[0]=='/')c[i]=1;
}
sort(a+1,a+n+1,cmp);
for (i=2;i<=n;i++)
if (a[i].a==a[i-1].a) d[a[i].d]=a[i-1].d,u[a[i-1].d]=a[i].d;
for (i=1;i<=n;i++){
if (!r[0] && a[i].a>0 && !a[i].b) r[0]=a[i].d;
swap(a[i].a,a[i].b);
}
sort(a+1,a+n+1,cmp);
for (i=2;i<=n;i++)
if (a[i].a==a[i-1].a) l[a[i].d]=a[i-1].d,r[a[i-1].d]=a[i].d;
i=0;
sum=0;
k=4;bz1=true;
while (sum<s){
bz[i][k]=sum;
if (k==1) l1=u[i];
if (k==2) l1=d[i];
if (k==3) l1=l[i];
if (k==4) l1=r[i];
if (abs(x[l1]-x[i])+abs(y[l1]-y[i])+sum<=s && l1){
sum+=abs(x[l1]-x[i])+abs(y[l1]-y[i]);
if (c[l1]==1){
if (k==1) k=4;
else if (k==2) k=3;
else if (k==3) k=2;
else k=1;
}else{
if (k==1) k=3;
else if (k==3) k=1;
else if (k==2) k=4;
else k=2;
}
i=l1;
if (bz[i][k] && bz1){
bz1=false;
p=sum-bz[i][k];
s=(s-sum)%p;sum=0;
}
}else{
xx=x[i];yy=y[i];
if (k==1) yy+=s-sum;
if (k==2) yy-=s-sum;
if (k==3) xx-=s-sum;
if (k==4) xx+=s-sum;
printf("%lld %lld\n",xx,yy);return 0;
}
}
printf("%lld %lld\n",x[i],y[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: