http://acm.nyist.net/JudgeOnline/problem.php?pid=6
典型的贪心,最优装载问题。
每个喷水口最大覆盖长度为:2*sqrt(a[i]*a[i]-1把喷水口半径从大到小排列,从最大的开始取就可以。
注意:半径1以及以下的喷水装置不能覆盖长度。但题目中说每个喷水装置的效果都会让以它为中心的半径为实数Ri(的圆被湿润,不考虑r<1的情况
/*2015-7-30 21:24:11
贪心。
一个圆能覆盖的区间长度为: len = 2*sqrt(r*r-1*1)
*/
nyoj——6代码如下(已AC)<pre class="plain" name="code">#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
bool cmp(double a,double b)//bool为布尔型,只有一个字节,取值false和true,是0和1的区别通常用来存储关系表达式或者逻辑表达式的结果
{
return a>b; // 从大到小排序
}
double l(double r)
{
return 2*sqrt(r*r-1*1);
}
int main()
{
int m,n,i;
double a[610];//数组一般开的范围要偏大 否则会越界(runtime error)
scanf("%d",&m);
while(m--)
{
double sum=0;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%lf",&a[i]);
sort(a,a+n,cmp); // 喷水装置半径从大到小排序
for(i=0;i<n;i++)
{
sum+=l(a[i]);
if(sum>=20)
break; //跳出循环(不可少)
}
printf("%d\n",i+1); //i从0开始的 结果i+1 若从1开始 结果直接输出i
}
return 0;
}
<pre class="plain" name="code">考虑r<1的情况时 代码如下
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int cmp(double a,double b)
{
return a>b;
}
double f(double R) //求出每个喷水装置覆盖的长度
{
return 2*sqrt( (double)(R*R-1) );
}
int main()
{
int T,m,i,k;
double sum,t,a[1010];
scanf("%d",&T);
while(T--)
{
memset(a,0,sizeof(a));
scanf("%d",&m);
for(i=0,k=0; i<m; i++)
{
scanf("%lf",&t);
if(t>1)
a[k++] = t;//将半径大于一的喷水装置存入数组,装置个数为k。
}
sort(a,a+k,cmp); //快排,将喷水装置的覆盖长度,由大到小排序
for(i=0,sum=0.0; i<k; i++)
{
sum+=f(a[i]);
if(sum>=20.0)
{
break;
}
}
printf("%d\n",i+1);
}
return 0;
}