码迷,mamicode.com
首页 > 其他好文 > 详细

1780 - 2019年我能变强组队训练赛第十八场

时间:2019-09-21 19:27:57      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:scan   题解   main   不同   ret   nbsp   ++z   输出   oar   

题目描述

wls有一个钟表,当前钟表指向了某一个时间。
又有一些很重要的时刻,wls想要在钟表上复现这些时间(并不需要依次复现)。我们可以顺时针转动秒针,也可以逆时针转动秒针,分针和时针都会随着秒针按规则转动,wls想知道秒针至少转动多少角度可以使每个时刻至少都会被访问一次。
注意,时钟上的一种时针分针秒针的组合,可以代表两个不同的时间。

 

输入

第一行一个整数n代表有多少个时刻要访问。
第二行三个整数h,m,s分别代表当前时刻的时分秒。
最后n行每一行三个整数hi,mi,si代表每个要访问的时刻的时分秒。
1≤n≤86,400
0≤h,hi<24
0≤m,mi,s,si<60

 

输出

输出一行一个数代表秒钟转的角度,答案保留两位小数。

 

样例输入

1
0 1 0
0 1 1

样例输出

6.00

Contest1780 - 2019年我能变强组队训练赛第十八场 clock

题解:把时间排序去重后进行顺时针及逆时针的暴力;

例如顺时针暴力是:枚举每一个点,让开始时间先顺时针到这个点,再逆时针从这个点到这个点的下一个点;

逆时针暴力和顺时针差不多,只是把方向都换一下就好,就是先让开始时间先逆时针到一个点,再顺时针从这个点到下一个

 
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+7;
int Min=1000000007;
struct node
{
    int hi,mi,si,miao;//miao是把时间转换为秒来计算
} Time[100005],start;
bool cmp(node a,node b)
{
    return a.miao<b.miao;
}
int atob(node a,node b,int f)//时间a到时间b,f=0代表逆时针,f=1代表顺时针
{
    if(f==0)
    {
        if(b.miao>a.miao)
        {
            return (43200-b.miao+a.miao)*6;
        }
        return (a.miao-b.miao)*6;
    }
    if(b.miao<a.miao)
        return (43200-a.miao+b.miao)*6;
    return (b.miao-a.miao)*6;;
}
int main()
{
    int n;
    scanf("%d",&n);
    scanf("%d %d %d",&start.hi,&start.mi,&start.si);
    if(start.hi>=12)start.hi=start.hi-12;
    start.miao=start.hi*3600+start.mi*60+start.si;
    for(int i=1; i<=n; ++i)
    {
        scanf("%d %d %d",&Time[i].hi,&Time[i].mi,&Time[i].si);
        if(Time[i].hi>=12)Time[i].hi=Time[i].hi-12;
        Time[i].miao=Time[i].hi*3600+Time[i].mi*60+Time[i].si;
    }
    sort(Time+1,Time+n+1,cmp);//按miao进行排序
    int z=1,len=1;
    for(; z<=n; ++z)//找到第一个与开始时间不一样的,就是排序去重的第一步
        if(Time[z].miao!=start.miao)
        {
            Time[1]=Time[z];
            break;
        }
    for(int i=z+1; i<=n; ++i)//排序去重
        if(Time[i].miao!=Time[len].miao&&Time[i].miao!=start.miao)Time[++len]=Time[i];
    int poi=0;
    for(int i=1; i<=len; ++i)//找到第一个大于start的时间
        if(Time[i].miao>start.miao)
        {
            poi=i;
            break;
        }
    if(poi==0)//如果所有时间都小于开始时间
    {
        Min=min(Min,atob(start,Time[1],0));
        for(int i=1; i<len; ++i)
        {
            Min=min(Min,atob(start,Time[i],1)+atob(Time[i],Time[i+1],0));
        }
        Min=min(Min,atob(start,Time[len],1));
        for(int i=len;i>1;--i){
            Min=min(Min,atob(start,Time[i],0)+atob(Time[i],Time[i-1],1));
        }
        printf("%d.00\n",Min);
        return 0;
    }
    for(int i=poi-1; i<=len; ++i)
    {
        if(i==poi-1)
        {
            int temp=atob(start,Time[poi],0);
            Min=min(Min,temp);
        }
        else if(i==len&&poi==1)
        {
            int temp=atob(start,Time[len],1);
            Min=min(Min,temp);
        }
        else
        {
            int temp=atob(start,Time[i],1),x=i+1;
            if(i==len)x=1;
            temp+=atob(Time[i],Time[x],0);
            Min=min(Min,temp);
        }
    }
    for(int i=1; i<poi; ++i)
    {
        if(i==poi-1)
        {
            int temp=atob(start,Time[poi-1],1);
            Min=min(Min,temp);
        }
        else
        {
            int temp=atob(start,Time[i],1);
            temp+=atob(Time[i],Time[i+1],0);
            Min=min(Min,temp);
        }
    }
    for(int i=poi-1;i>=1;--i){
        if(i-1==0)
            Min=min(Min,atob(start,Time[i],0)+atob(Time[i],Time[len],1));
        else Min=min(Min,atob(start,Time[i],0)+atob(Time[i],Time[i-1],1));
    }
    for(int i=len;i>poi;--i){
        Min=min(Min,atob(start,Time[i],0)+atob(Time[i],Time[i-1],1));
    }
    printf("%d.00\n",Min);
    return 0;
}

  

1780 - 2019年我能变强组队训练赛第十八场

标签:scan   题解   main   不同   ret   nbsp   ++z   输出   oar   

原文地址:https://www.cnblogs.com/lengsong/p/11563848.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!