• HDU 5114 Collision


    题目链接:HDU-5114

    题意为给一个矩形n*m,两个给定坐标的球在矩形中都以(1,1)的速度运动,碰到边界会反弹,求第一次碰撞的坐标。

    思路是首先把运动分解为横向运动和纵向运动分别考虑,则变成两个追赶运动。假设(x_2>x_1,y_2>y_1),可以得到x坐标相同的时间为(t_x=n - frac{x_2-x_1}{2}-x_1+kn = n - frac{x_1+x_2}{2}+kn ),y坐标相同时间为(t_y=m - frac{y_2-y_1}{2}-y_1+k'm = m - frac{y_1+y_2}{2}+k'm ),其中 k,k' >= 0。

    于是我们就可以得到(t= m - frac{y_1+y_2}{2}+k'm =n - frac{x_1+x_2}{2}+kn),变换就是我们熟悉的(kn - k'm = (m - frac{y_1+y_2}{2})-(n - frac{x_1+x_2}{2})),也就是二元一次方程求最小非负整数解。

    但是这里面还有一个问题,就是方程中由于有(frac{y_1+y_2}{2})和(frac{x_1+x_2}{2}),存在小数。所以我们把所有值全部提前*2,这里可以理解为所有坐标和矩形尺寸全部拉伸为原来的两倍。

    于是方程变成了(2nk - 2mk' = (2m - y_1 - y_2)-(n - x_1 - x_2)),求解即可。

    题目中还有一些需要注意的细节,比如((x_1=x_2 ,y_1=y_2)),((x_1=x_2 ,y_1!=y_2)),((x_1!=x_2 ,y_1=y_2))三种情况,并不满足上述方程,需要特判。

    代码如下:

     1 #include<cstdio>
     2 #include<set>
     3 #include<map>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<queue>
     7 #include<iostream>
     8 using namespace std;
     9 typedef long long LL;
    10 
    11 
    12 //拓展欧几里得算法
    13 //求ax+by=gcd(a,b)的一组解
    14 //其他解为x=x0+kb',y=y0-ka'
    15 //a'=a/gcd(a,b),b'=b/gcd(a,b)
    16 LL extgcd(LL a,LL b,LL &x,LL &y)
    17 {
    18     LL d=a;
    19     if(b!=0)
    20     {
    21         d=extgcd(b,a%b,y,x);
    22         y-=(a/b)*x;
    23     }
    24     else { x=1; y=0; }
    25     return d;
    26 }
    27 
    28 //求最大公约数
    29 LL gcd(LL a,LL b)
    30 {
    31     if(b==0) return a;
    32     return gcd(b,a%b);
    33 }
    34 
    35 
    36 int main()
    37 {
    38 #ifdef LOCAL
    39     freopen("in.txt","r",stdin);
    40 #endif
    41     LL t;
    42     scanf("%lld",&t);
    43     for(LL tt=1;tt<=t;tt++)
    44     {
    45         printf("Case #%lld:
    ",tt);
    46         LL n,m,x1,x2,y1,y2;
    47         scanf("%lld%lld%lld%lld%lld%lld",&n,&m,&x1,&y1,&x2,&y2);
    48         LL t2;
    49         LL tx2=(2*n-x1-x2),ty2=(2*m-y1-y2);
    50         if(x1==x2 && y1==y2) {printf("%.1lf %.1lf
    ",1.0*x1,1.0*y1); continue;}
    51         else if(x1==x2) t2=ty2;
    52         else if(y1==y2) t2=tx2;
    53         else
    54         {
    55             LL k,kk;
    56             LL g=extgcd(2*n,2*m,k,kk);
    57             LL tmp=ty2-tx2;
    58             if(tmp%g)
    59             {
    60                 printf("Collision will not happen.
    ");
    61                 continue;
    62             }
    63             else
    64             {
    65                 k=tmp/g*k;
    66                 LL mm=2*m/g;
    67                 k=(k % mm + mm) % mm;
    68                 t2=tx2+k*2*n;
    69                 if(t2<ty2) t2+=(ty2-t2)/k*k;
    70                 if(t2<ty2) t2+=k;
    71             }
    72         }
    73         LL xx=(2*x1+t2)%(2*n);
    74         LL yy=(2*y1+t2)%(2*m);
    75         if(((2*x1+t2)/(2*n))%2) xx=2*n-xx;
    76         if(((2*y1+t2)/(2*m))%2) yy=2*m-yy;
    77         printf("%.1lf %.1lf
    ",xx/2.0,yy/2.0);
    78     }
    79     return 0;
    80 }
  • 相关阅读:
    TLS握手、中断恢复与证书中心的原因
    PROC 文件系统调节参数介绍(netstat -us)
    CPU状态信息us,sy,ni,id,wa,hi,si,st含义
    优化Linux内核参数
    linux内核(kernel)版本号的意义
    ethhdr、ether_header、iphdr、tcphdr、udphdr 结构介绍
    linux下将不同线程绑定到不同core和cpu上——pthread_setaffinity_np
    module_init的加载和释放
    (一)洞悉linux下的Netfilter&iptables:什么是Netfilter?
    netfilter的钩子——数据包在内核态得捕获、修改和转发
  • 原文地址:https://www.cnblogs.com/zarth/p/6534156.html
Copyright © 2020-2023  润新知