美文网首页
杭电-1006 Tick and Tick

杭电-1006 Tick and Tick

作者: 这样你就找不到我了 | 来源:发表于2020-01-21 19:19 被阅读0次

这题需要一些耐心,准备好了就来吧。

我们理解题目意思的时候注意,
A hand is happy if it is at least D degrees from any of the rest.
这句话并不是谷歌翻译的那样
“如果一只手与其余任何一只手至少有D度,那它就是快乐的”
其实题目要求是与其余所有的手(2只)都相距D度,它才是快乐的。

另外,
1,时间是连续的,三根指针之间的位置是有关系的,不能随意摆放。
2,一个圈是360度

指针之间大于D度的情况,可以描述如图

首先想到的思路是穷举所有时间,将一天24小时指针的位置全部记录下来,然后计算出结果。

另外由于24小时实际是在表盘上走了2圈,我们可以简化为求1圈的数据,即12小时指针的情况就行了。

但是按秒穷举所有时间实在太慢,我参考了前辈的思路:

零点时,三针合一,
两两指正的距离为0,
然后指针慢慢分开,
不难想象,当两两指针分开距离 全部都 超过D时,满足题目条件,
然后它们会再度重合,重新开始。(可以联系钟表想象一下其它三针合一的情况)

这样,在 重合 -> 再次重合 的过程中,有一段连续的距离是满足题目条件的。

这个距离可以这样描述 :
两两指针分离到D所用时间的最大值 (3个指针,两两看做一组)-------->

两两指针分离到D后,继续分离,到360-D距离所用时间的最小值(360-D其实就是从圆的另一端看,两指针距离小于D的情况,此时刚好不满足题目要求)

之所以是最大值是因为题目要求 全部距离D以上 ,所以必须等那三个组合中最慢的那一个完全分开D距离。

之所以是最小值同理,一旦有一个组合不满足 距离大于D 的要求,则整个系统不满足题目要求。


我们可以遍历所有指针重复的情况,并在从重复 走向 下一次重复的过程中,取符合题目要求的时间段,继而计算出结果。

具体思路见代码(已AC):

#include <iostream>
#include <algorithm>

using namespace std;
const int maxn=12*60*60;

double Max(double a,double b,double c)
{
    return max(max(a,b),c);
}
double Min(double a,double b,double c)
{
    return min(min(a,b),c);
}

int main(){
    double D;

    while(scanf("%lf",&D)&&D!=-1){
        double vh,vm,vs;//角速度,per秒
        vs = 6.0;
        vm = 1.0/10;
        vh = 1.0/120;

        double i,j,k;
        double ans=0,p,q;


        //两两指针之间运动到完全重合的时间————每过这么一段时间,该两指针就会重合
        double t_hm,t_hs,t_ms,a[7];
        t_hm = 360/(vm-vh);
        t_hs = 360/(vs-vh);
        t_ms = 360/(vs-vm);
        
        //两两指针运动 出 到相距为d的时间
        a[0] = D/(vm-vh);
        a[1] = D/(vs-vh);
        a[2] = D/(vs-vm);

        //两两指针运动 回 到相距为d的时间
        a[3] = (360-D)/(vm-vh);
        a[4] = (360-D)/(vs-vh);
        a[5] = (360-D)/(vs-vm);

        
        /*
            每一次两两指针一出一回之间,必有一段连续的距离大于D,当任意两两指针之间的距离都大于D时,满足题目要求
            再进一步分析可知,
            “两两指针运动 出 到相距为d的时间” 应取最大,因为题目要求所有的指针都happy
            “两两指针运动 回 到相距为d的时间” 应取最小,因为一旦有一对指针“回来了(相距距离小于d)”,则不满足大家都happy的题目要求
        */
    
        for(i=0;i<=1.0*maxn;i+=t_hm)
            for(j=0;j<=1.0*maxn;j+=t_hs){
                if(j+a[1]>i+a[3])break;//p>=j+a[1]&&q<=i+a[3]=>p>q=>无效
                if(i+a[0]>j+a[4])continue;
                for(k=0;k<=1.0*maxn;k+=t_ms)
                {
                    // if(k+a[2]>i+a[3]||k+a[2]>j+a[4])break;
                    // if(i+a[0]>k+a[5]||j+a[1]>k+a[5])continue;
                    p=Max(i+a[0],j+a[1],k+a[2]);//在这三个时间段刚好完成分离n度,所以取最大值才能保证全都分离n以上
                    q=Min(i+a[3],j+a[4],k+a[5]);//在这三个时间段刚好完成合并n度,所以取最小值才能保证全都未合并到n以内
                    // cout << p <<endl<< q <<endl;
                    if(q > p){
                        // cout << ans << endl;
                        ans+=q-p;
                    }
                }
            }
        printf("%.3lf\n",100.0*ans/maxn);
    }
    return 0;
}

由于本人技术比较菜,调Bug调到怀疑自我,导致此代码和其它来源代码部分雷同,见谅。

相关文章

  • 杭电-1006 Tick and Tick

    这题需要一些耐心,准备好了就来吧。 我们理解题目意思的时候注意,A hand is happy if it is ...

  • 2022-05-03

    fastadmin 打卡 tick 淘宝币 打卡 tick write log 打卡 tick. 背单词...

  • 《Tick Tick Boom》

    其实我一直在思考到底Jon听见的倒数是什么?当然从本人的经历来看,这很有可能是生命时刻的倒数,但在我看来,这更像是...

  • 2022-05-02

    fastadmin 打卡 tick 淘金币 打卡 tick 背英语单词 打卡 tick 今日必做之事: 找...

  • [shared hook]GM/Tick

    原文链接:GM/Tick 函数原型: GM:Tick() 描述: 每一server tick都会被调用, 在服务器...

  • Tick or Tick 时钟问题

    一个很绕的计算题 hdu~[Tick and Tick]http://acm.hdu.edu.cn/showpro...

  • linux tickGet()

    tickGet()返回的是从系统启动开始tick计数后的总的tick数目。 tick是啥,是“滴答”,它是一个数值...

  • 10. ggplot2坐标轴刻度位置(breaks)和标签(la

      axis tick marks和legend tick marks是scale breaks的特殊案例,通过s...

  • nextTick

    前言 可先看EventLoop具体参见src/core/util/next-tick.js 什么是tick?Eve...

  • Go定时任务

    1.time.Sleep方法 2.time.Tick函数: 3. Tick,Sleep,包括time.After函...

网友评论

      本文标题:杭电-1006 Tick and Tick

      本文链接:https://www.haomeiwen.com/subject/vtwezctx.html