洛谷春季ACM多校赛 Final Spark

题目描述

有一个长无限,宽为 w + t 的长方形,去切割一个半径为 S 的圆,问如何切割可以使得其切割所对应的弧最长,求其占据的比例,一共有T组测试数据
洛谷春季ACM多校赛 Final Spark_第1张图片
洛谷春季ACM多校赛 Final Spark_第2张图片

样例
3
20 20 20 1000
0 0 100 1000
100 100 198 2000
1.000000000
0.000000000
0.503215306
思路

1、如果 w+t >= 2*s ,那么是长方形是完全覆盖的,覆盖率为 1
2、如果 w+t==0,那么覆盖率为 0
3、根据page1, 想要求中间切割弧长的情况,我们可以通过切割圆的这个长度来计算,宽切割是一定的,长切割是会变化的,所以我们需要通过长来确定大小,就是求切割的两边长的最小值,长就是我图中红色描的线。我们把圆切开来分成两半只看正半轴情况,根据page2,求导(其实看看就看得出来),很容易发现越往边上移动切割长变化的速度是加快的,而越靠近中间的切割长的增速是很慢的。
洛谷春季ACM多校赛 Final Spark_第3张图片
我们就用上半圆来进行求解,请看我画的图,u1s1比较丑,不要介意
所以根据这个,我们就可得知,有一条边是与圆边上相切的。接下来的求解就简单了,角度除以360度,这边为了方便我只计算一半
然后分成两个小情况
我用画图的形式表示了
1、w + t >= s
2、w + t < s
洛谷春季ACM多校赛 Final Spark_第4张图片
太丑了,不要介意 233333333
注意点和思路讲完了,我就贴代码了

代码片
#include
using namespace std;

double Abs(double x) {
	return x>=0?x:-x;
}

void solve() {
	double w,t,s,d;
	scanf("%lf %lf %lf %lf",&w,&t,&s,&d);
	if ( (w+t)/2.0>=s ) printf("1.000000000\n");
	else if ( w+t==0 ) printf("0.000000000\n");
	else if ( w+t>=s ) printf("%.9f\n",1.0 - acos(Abs(s-(w+t))/s) / acos(-1.0));
	else printf("%.9f\n",acos(Abs(s-(w+t))/s) / acos(-1.0));
}

int main() {
	//freopen("in.txt","r",stdin);
	int t;
	scanf("%d",&t);
	while(t--) {
		solve();
	}
	return 0;
}

你可能感兴趣的:(比赛)