本题需要一定的数学抽象能力,为了选择尽量少的喷水装置,我们由朴素的数学经验可以知道
1.需要将每个装置的覆盖面积最大化
2.单个装置覆盖半径尽可能大
由2.我们得到一个推论
推论1.输入n个喷水装置,若最少可以用k个装置覆盖,则将n个装置按照半径大小降序排列的前k个,必为满足条件的一组解
(该推论可以利用反证法证明,即假设其中一个不为降序的前k个,而是后方的第i个,若满足,且前k个必定能将后方的第i个全覆盖,即将i替换为前k个必成立)
接下来我们思考有效覆盖面积的问题,因为是用圆去覆盖长方形,且只能在中心线上覆盖,由此我们得到推论二。
推论2.每个圆的有效覆盖面积为其宽为2的内接长方形的面积
由推论2.我们可以得到推论三。
推论3.半径小于1的圆为无效覆盖圆,若选用半径小于一的圆,必定还需要一个大于一的圆重叠在其之上才能全覆盖,故该圆为无效覆盖圆
因为所有圆的内接长方形宽均为2,所以我们可以用长度来代替其面积,长度为L=
于是问题被我们简化为了在所有输入半径中,取L的降序排列,并相加,看加到哪一项时,满足,相加项的个数即为最小值。
#include <iostream>
#include <cmath>
using namespace std;
void bsort(float a[],int n)
{
int i,j;
float t;
for(i=1;i<=n-1;i++){
for(j=0;j<=n-1;j++){
if(a[j]<a[j+1]){
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
}
float cal(float k)
{
float s;
s=sqrt(k*k-1);
return s;
}
int main()
{
int i,n;
float s=0;
cin>>n;
float a[n];
for(i=0;i<=n-1;i++){
cin>>a[i];
}
bsort(a,n);
for(i=0;i<=n-1;i++){
a[i]=cal(a[i]);
}
for(i=0;i<=n-1;i++){
s=s+2*a[i];
if(s>=20){
cout<<i+1;
break;
}
}
return 0;
}