[蓝桥杯][算法提高VIP]Lots of Sunlight

[蓝桥杯][算法提高VIP]Lots of Sunlight

时间限制: 1Sec 内存限制: 128MB 提交: 6 解决: 0

题目描述

公寓建设管理公司(Apartment Construction Management, 简称ACM)在上海郊区新建了几栋高层公寓楼。由于经济增长极为迅速,ACM期望通过出租房屋获得客观的利润。ACM打广告宣称他们的公寓比附近其他的公寓都要好,因为他们的公寓采光更好。没有其他的建筑物阻挡阳光直射到ACM的公寓楼上。
ACM想要证明自己的广告没有虚假成分,于是他们决定告诉潜在住户们每栋楼的采光究竟怎样。为了给消费者们有代表性的数据,公司决定将2005年4月5日的阳光直射时长写入广告。在那一天,上海于早上5点37分日出,于下午6点17分日落。



如上图所示,公寓楼从东至西排列,每栋楼有若干层,每层有一间公寓。公寓门牌号的后两位代表楼栋编号,最东侧的楼编号为01,从东至西编号递增。门牌号的其他所有位则代表楼层,1为一层,2为二层,以此类推。
太阳从东方升起,以恒定角速度划过天空,然后从西方落下。阴影仅由楼房投射出(也即,每栋楼可以投影到一栋或者多栋其他的楼房上)。当一间公寓的整块东侧或西侧外墙被太阳直射,或者当太阳处于公寓正上方时,我们就认为公寓受到太阳直射。

输入

输入含有若干组测试数据。一组测试数据首先含有一行,包括一个整数n,代表公寓楼的数量。接下来一行有两个整数w和h,分别代表一间公寓的宽度(东-西方向)和高度,单位为米。接下来一行有2n-1个整数,记作m(1), d(1), m(2), d(2), ... , d(n-1),m(n)。m(i)为编号为i的公寓楼的层数,d(i)为编号为i和i+1的公寓楼之间的距离,单位为米。
接下来的一行包含若干整数,以0结尾。每个整数代表求编号为这个整数的公寓的太阳直射时间。输入的最后一行仅包含一个整数0,你不需要处理这一行。
最多含有10组测试数据。

输出

对于每组数据,输出数据组数的编号。然后对于每个询问,用24小时格式输出太阳直射时间的起止时刻。所有时间向下取整到秒。允许输出与答案有最大1秒的误差。如果输入中含有不存在的公寓的编号,请将其指出。请按照样例输出中的格式输出。

样例输入

3
6 4
5 6 3 3 4
302 401 601 303 0
4
5 3
4 5 7 8 5 4 3
101 302 503 0
0

样例输出

Apartment Complex: 1
Apartment 302: 10:04:50 - 13:23:47
Apartment 401: 05:37:00 - 17:13:57
Apartment 601: Does not exist
Apartment 303: 09:21:19 - 18:17:00
Apartment Complex: 2
Apartment 101: 05:37:00 - 12:53:32
Apartment 302: 09:08:55 - 14:52:47
Apartment 503: 09:01:12 - 18:17:00

问题分析:

对于任意一个给定的房间,以下图中第2栋楼的202室为例,在太阳位于正上方的时候肯定可以完全被阳光照射。在这之前有一一个刚开始被照射的最小角度,最小角度取决于这栋楼左边的楼房对太阳光的遮挡。对左边的楼房一栋一栋地检查,以右上角的顶点为基准,连一条:线到所求房间的左下角,求这条线的倾斜角。倾斜角最大的线就是使得所求房间刚开始被太阳

光照射到的最小角度。同理,在这之后有一个刚结束被照射的最大角度,最大角度取决于右边的楼房对太阳光的遮挡。同样对右边的楼房一栋一 栋地检查,以左上角的顶点为基准,连一条线到所求房间的右下角,求这条线的倾斜角。倾斜角最小的线就是使得所求房间刚结束被太阳光照射到的最大角度,如图所示。最后将这两个角度转化成时间并输出。

代码如下:

#include<cstdio>
#include<math.h>
int n,h[111],d[111],width,height,sum,i,di,num,level,id;
int cases,dh,dw,h1,m1,h2,m2;
double min,max,angle,Half_pi;//min和max向下取整对应的开始时间和结束时间的秒,half_Pi为π/2 angle存储照射角 
int main()
{
	Half_pi=acos(0);
	while(scanf("%d",&n) && n)
	{
		scanf("%d%d",&width,&height);
		sum=0;
		for(i=0;i<n;i++)
		{
			scanf("%d",&h[i]);
			d[i]=sum;
			if(i<n-1)
			{
				scanf("%d",&di);
				sum+=di+width;
			}
		}
		int flag=1;
		//printf("Apartment Complex: %d\n",++cases);
		while(scanf("%d",&num)&&num)
		{
			if(flag==1)
			{
				printf("Apartment Complex: %d\n",++cases);
				flag=0;	
			}
			printf("Apartment %d: ",num);
			level=num/100-1;
			id=num%100-1;
			if(id<0 || id>=n || level<0 || level>=h[id])
			{
				puts("Dose not exist");
				continue;
			}
			min=0;
			max=0;
			for(i=0;i<id;i++)
			{
				dw=d[id]-d[i]-width;
				dh=height*(h[i]-level);
				if(dh>0)
				{
					angle=asin(dh/sqrt(dh*dh+dw*dw));
					if(angle>min)
					{
						min=angle;
					}
				}
			}
			for(i=id+1;i<n;i++)
			{
				dw=d[i]-d[id]-width;
				dh=height*(h[i]-level);
				if(dh>0)
				{
					angle=asin(dh/sqrt(dh*dh+dw*dw));
					if(angle>max)
					{
						max=angle;
					}
				}
			}
			min=20220+22800*min/Half_pi;
			max=65820-22800*max/Half_pi;
			h1=int(min/3600);
			min-=h1*3600;
			m1=int(min/60);
			min-=m1*60;
			h2=int(max/3600);
			max-=h2*3600;
			m2=int(max/60);
			max-=m2*60;
			printf("%02d:%02d:%02d-%02d:%02d:%02d\n",h1,m1,int(min),h2,m2,int(max));
		}
	}	
	return 0;
} 

运行结果:




 


如有不足之处,欢迎指正!!!

猜你喜欢

转载自blog.csdn.net/xyqqwer/article/details/88048383