喷水装置(一)
时间限制:
3000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
现有一块草坪,长为20米,宽为2米,要在横中心线上放置半径为Ri的喷水装置,每个喷水装置的效果都会让以它为中心的半径为实数Ri(0<Ri<15)的圆被湿润,这有充足的喷水装置i(1<i<600)个,并且一定能把草坪全部湿润,你要做的是:选择尽量少的喷水装置,把整个草坪的全部湿润。
-
输入
-
第一行m表示有m组测试数据
每一组测试数据的第一行有一个整数数n,n表示共有n个喷水装置,随后的一行,有n个实数ri,ri表示该喷水装置能覆盖的圆的半径。
输出
-
输出所用装置的个数
-
2 5 2 3.2 4 4.5 6 10 1 2 3 1 2 1.2 3 1.1 1 2
样例输出
-
2 5
-
样例输入
-
第一行m表示有m组测试数据
分析题意:
每一个喷水装置的喷水范围是一个圆,园的半径越大,喷射的范围越广。要想所用的喷水装置最少,可以考虑将喷水按照半径有大到小排列,依次使用。效果图如下(自制的,嘻嘻):
![]()
其中,r1,r2,r3是喷水装置的半径,l1,l2,l3是喷水装置在水平方向的有效喷射距离的一半。根据上图即可设计算法来实现求解问题。算法实现:
对所有的喷水装置半径按从大到下的顺序排序,根据勾股定理依次计算l1,l2,l3.....的长度,每计算一次就乘以2再累加到总长度L上。若L第一次出现L>=20.0,则输出此时已经累加的喷水装置的个数。代码实现
#include<stdio.h> #include<math.h> //勾股定理函数 float Tri(float c, float a) { return sqrt(c*c - a*a); } int main() { int m,n; float a[601], sum,t; scanf("%d", &m); while (m--) { sum = 0.0; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%f", &a[i]);//依此读入数组,准备排序 } //排序算法(冒泡) for (int i = 0; i < n - 1; i++) { for (int j = i + 1; j < n; j++) { if (a[i] < a[j]) { t = a[i]; a[i] = a[j]; a[j] = t; } } } //从高到低开始选择 for (int i = 0; i < n; i++) { sum += (2*Tri(a[i],1.0)); if (sum >= 20) { printf("%d\n", i + 1); break; } } } getchar(); getchar(); return 0; }
下面是该题目站点推荐的参考答案:
#include<iostream> #include<vector> #include<functional> #include<algorithm> #include<cmath> using namespace std; double Length(double R,double b) { return 2*sqrt(R*R-b*b/4); } int main() { const double l=20,w=2; int n; cin>>n; while(n--) { int m; cin>>m; double R; vector<double> Rs; while(m--) { cin>>R; Rs.push_back(R); } sort(Rs.begin(),Rs.end(),greater<double>()); double sum=0; int i; for(i=0;i!=Rs.size();i++) { if (sum>l) break; sum+=Length(Rs[i],w); } cout<<i<<endl; } }
以上就是我对该题的解答,有疑问的小伙伴欢迎跟我交流~~~