【NOIP模拟赛】弹球

弹球(happen)

【问题描述】

在一个x*y的矩形区域内有两个弹球,这两个弹球的初始位置分别是(x1,y1)和(x2,y2)。
现在这两个弹球都保持着(1,1)的速度运动(即向右上角运动),遇到矩形区域的边界会反弹回来(满足反射定律)。
问这两个弹球第一次相遇的位置,如果它们不能相遇则输出“no happen”。

【输入格式】 从文件happen.in中读入数据。

第一行,两个整数x和y,表示矩形的区域规格。
第二行四个整数x1,y1,x2,y2分别表示两个弹球的初始位置。

【输出格式】 输出到文件happen.out中。

如果两个弹球会相遇,则输出第一次相遇的位置,保留一位小数;否则输出“no happen”。

【数据规模】

30%数据,1≤x,y≤5000
100%数据,1≤x,y≤100000; 0≤x1, x2≤x; 0≤y1, y2≤y

分析

考试的时候竟然没有想到模拟,但这题扩展欧几里得算法也是可以做的。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int x,y;
int s1,t1,s2,t2;
double a,b,c,d,ansx=-1,ansy;
bool flag1,flag2;
struct node{
    double x,y;
}p,q;
int main(){
    freopen("happen.in","r",stdin);
    freopen("happen.out","w",stdout);
    x=read();y=read();
    s1=read();t1=read();s2=read();t2=read();
    a=b=c=d=0.5;
    if(s1==s2&&t1==t2){printf("%.1lf %.1lf
",s1*1.0,t1*1.0); return 0;}
    p.x=s1;p.y=t1;q.x=s2;q.y=t2;
    do{
        if(p.x+a<0||p.x+a>x) a*=-1;
        if(p.y+b<0||p.y+b>y) b*=-1;
        if(q.x+c<0||q.x+c>x) c*=-1;
        if(q.y+d<0||q.y+d>y) d*=-1;
        p.x+=a;p.y+=b;q.x+=c;q.y+=d;
        if(p.x==q.x&&p.y==q.y){
            ansx=p.x; ansy=p.y;
            break;
        }
        if(p.x==s1&&p.y==t1) flag1=true;
        if(q.x==s2&&q.y==t2) flag2=true;
    }while(!flag1||!flag2);
    if(ansx>=0)
        printf("%.1lf %.1lf
",ansx,ansy);
    else printf("no happen
");
    return 0;
}
原文地址:https://www.cnblogs.com/huihao/p/7778436.html