http://acm.nyist.net/JudgeOnline/problem.php?pid=6
java1:
主要用到贪心算法。
由题目很明显可以得出只要是半径大于1的喷水装置都是可以被选中的,每个装置能够湿润草坪的有效长度为2*sqrt(r*r-1);题目要我们求的是要选择尽量少的的喷水装置,所以可以贪心一下,先按半径从大到小的顺序排序一下,然后for()或while()一下就搞定。
import java.util.*;
public class Main {
public static void main(String args[]) {
Scanner cin = new Scanner(System.in);
int count,a;
count=cin.nextInt();
while (count>0) {
a = cin.nextInt();
List<Double> arrs=new ArrayList<Double>();
double sum=0;
int result=0;
for(int i=0;i<a;i++)
{
arrs.add(cin.nextDouble());
}
Collections.sort(arrs,new Comparator<Double>() {
public int compare(Double o1, Double o2) {
//不能直接相减丢失精度。
//System.out.println("a2="+o2+",a1="+o1+",o3="+(o2-o1));
if(o2>o1)
{
return 1;
}else{
return -1;
}
}
});
for(int j=0;j<arrs.size();j++)
{
double val=arrs.get(j);
if(val<=1.0)
{
//已经要使用1了
break;
}
if(sum>=20.0)
{
break;
}else{
sum+=2*(double)(Math.sqrt(val*val-1));
result++;
}
}
System.out.println(result);
count--;
}
cin.close();
}
}
java2:
乍起来有点不知如何下手, 其实只要算出 这个草地的斜边长度, 然后只要全部圆的半径合大于等于这个斜边长度的一半就可以了(但是必须丢弃半径小于等于1的装置,在横中线上无论怎么放,它是无法完全覆盖草地的)。
import java.util.*;
public class Main {
public static void main(String args[]) {
Scanner cin = new Scanner(System.in);
int count,a;
count=cin.nextInt();
double len = Math.sqrt(20*20 + 2*2)/2;
while (count>0) {
a = cin.nextInt();
List<Double> arrs=new ArrayList<Double>();
double sum=0;
for(int i=0;i<a;i++)
{
arrs.add(cin.nextDouble());
}
Collections.sort(arrs,new Comparator<Double>() {
public int compare(Double o1, Double o2) {
if(o2>o1)
{
return 1;
}else{
return -1;
}
}
});
int j=0;
for( j=0;j<arrs.size();++j)
{
double val=arrs.get(j);
if(val<=1.0)
{
//已经要使用1了
break;
}
sum+=val;
if(sum>=len)
{
break;
}
}
System.out.println(j+1);
count--;
}
cin.close();
}
}
最优答案:
#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;
}
}