HDU-1006


title: HDU-1006
categories:

  • ACM
  • 盲集合求交
    tags:
  • 临界最优
  • 屏蔽细节
    date: 2020-02-14 11:10:09

一般我们的思维都是先找第一段符合题目的解,然后找第二段第三段,从而理解题目和找出规律。但对于有些题目,规律甚至第一段的解都非常难找,但如果我们知道解位于一个临界集合中,我们就可以不用去找这个解,转而寻找这个临界集合(因为寻找解非常复杂,寻找临界集合却比较容易),前提是可以把解从临界集合中分离出来(一般是临界集合的最值)。这样我们就可以避开寻找解这个非常复杂的过程,简化题目。

题目

滴答和滴答

*时间限制:2000/1000 MS(Java /其他)内存限制:65536/32768 K(Java /其他)
提交总计:26354接受提交:7208
*

问题描述

时钟的三只指针每秒旋转一次,并且每天相遇很多次。最后,他们对此感到无聊,并且每个人都希望远离其他两个人。如果一只手与其余任何一只手至少有D度,那它就是快乐的。您要计算一天中所有双手都开心的时间。

输入值

输入包含许多测试用例。他们每个人都有一条单行,其实数D在0和120之间(含0和120)。输入以-1的D终止。

输出量

对于每个D,用一行打印一天中所有手牌都高兴的时间百分比,精确到小数点后3位。

样本输入

0
120
90
-1

样本输出

100.000
0.000
6.251

算法

为什么暴力遍历每一秒不行

因为本题对精度有非常高的要求,这个表应该是静音表(扫秒表),不会发出滴答滴答的声音,并且要用到角速度,因为只有这样才能满足精度要求

分析

本题如果仔细思考求解的话,整个过程是非常复杂的,因为你不知道每一小段开始时究竟是那两个针到达临界值。既然这样那就求临界集合,将分针和时针从重合到再次重合看做一个大周期,将分针和表针从重合到再次重合看做一个周期,将时针和秒针从重合到再次重合看做一个小周期。一共有三个针,C32共有三种可能,也就是说每一小段的开始时刻必然在临界开始集合(分-时=n,秒-时=n,秒-分=n)中,并且是临界开始集合的最大值,而每一小段的结束必然存在于临界结束集合(分-时=360-n,秒-时=360-n,秒-分=360-n)中,并且是临界结束集合的最小值。这样只求两个临界集合就行了

代码

#include<iostream>
#include<stdio.h>
using namespace std;
double max(double a,double b,double c){
	double max=a>b?a:b;
	return max>c?max:c;
}
double min(double a,double b,double c){
	double min=a<b?a:b;
	return min<c?min:c;
}
int main()
{		freopen("input.txt", "r", stdin);
double n;
while(cin>>n&&n!=-1){

    double maxx=12*60*60; 
    double shij=30.0/60/60;
    double fenj=6/60.0;
    double miaoj=6/1.0;
    double sfx=fenj-shij;
    double smx=miaoj-shij; 

 	double fmx=miaoj-fenj;
 	
 	double sfz=360/sfx;
 	double sfn=n/sfx;
 	double sf_n=(360-n)/sfx;
 	
 	double fmz=360/fmx;
 	double fmn=n/fmx;
 	double fm_n=(360-n)/fmx;
 	
 	double smz=360/smx;
 	double smn=n/smx;
 	double sm_n=(360-n)/smx;
 	
 	double shichang=0;
 	for(double i=0;i<=maxx;i+=sfz)
 	{
 		for(double j=0;j<=maxx;j+=fmz)
 		{
 			if(j+fm_n<i+sfn) continue;
 			if(i+sf_n<j+fmn) break;
 			for(double k=0;k<=maxx;k+=smz)
 			{
 				if(k+sm_n<i+sfn||k+sm_n<j+fmn) continue;
 				if(j+fm_n<k+smn||i+sf_n<k+smn) break;
 				double kaishi=max(i+sfn,j+fmn,k+smn);
 				double jieshu=min(i+sf_n,j+fm_n,k+sm_n);
 				if(jieshu>kaishi)
 				shichang+=jieshu-kaishi;
 			}
 		}
 		
 	}
 	printf("%.3f\n",100.0*shichang/maxx);
 }
}
发布了25 篇原创文章 · 获赞 1 · 访问量 493

猜你喜欢

转载自blog.csdn.net/qq_43985303/article/details/104710089