题目描述
小明和朋友们一起去郊外植树,他们带了一些在自己实验室精心研究出的小树苗。
小明和朋友们一共有 n个人,他们经过精心挑选,在一块空地上每个人挑选了一个适合植树的位置,总共 n个。他们准备把自己带的树苗都植下去。
然而,他们遇到了一个困难:有的树苗比较大,而有的位置挨太近,导致两棵树植下去后会撞在一起。
他们将树看成一个圆,圆心在他们找的位置上。如果两棵树对应的圆相交,这两棵树就不适合同时植下(相切不受影响),称为两棵树冲突。
小明和朋友们决定先合计合计,只将其中的一部分树植下去,保证没有互相冲突的树。他们同时希望这些树所能覆盖的面积和(圆面积和)最大。
输入描述
输入的第一行包含一个整数 n ,表示人数,即准备植树的位置数。
接下来 n 行,每行三个整数 x,y,r,表示一棵树在空地上的横、纵坐标和半径。
其中,1≤n≤30,0≤x,y≤1000, 1≤r≤1000。
输出描述
输出一行包含一个整数,表示在不冲突下可以植树的面积和。由于每棵树的面积都是圆周率的整数倍,请输出答案除以圆周率后的值(应当是一个整数)。
输入输出样例
输入:
6
1 1 2
1 4 2
1 7 2
4 1 2
4 4 2
4 7 2
输出:
12
思路:
使用递归,种植最后一课树,记录种下的树的下标。计算面积。
当没有下一棵树时,记录最大面积。
判断已经种下的树同当前要种的树是否冲突,
不冲突则继续记录,面积相加,取面积最大值。
若冲突则不种下。
往前依次类推…,选择种和不种最终取最大面积。
完整代码
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static int N,ans=0,cnt=0;//ans面积,cnt已经种的树
public static int[]x=new int [31];
public static int[]y=new int [31];
public static int[]r=new int [31];
public static int[]tree=new int [31];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
N=scan.nextInt();
for(int i=0;i<N;i++){
//第i课树的横纵坐标和半径。
x[i]=scan.nextInt();
y[i]=scan.nextInt();
r[i]=scan.nextInt();
}
plant(0,0,0);
System.out.print(ans);
scan.close();
}
public static void plant(int i,int area,int cnt){
if(i==N){
//最后一棵树
if(area>ans){
//记录最大面积
ans=area;
}
return;
}
plant(i+1,area,cnt);
for(int j=0;j<cnt;j++){
//
if(dis(i,tree[j])){
//两树圆心距离小于两棵树的半径和
return ;
}
}
//选择种植的树,记录下标
tree[cnt]=i;
plant(i+1,area+r[i]*r[i],cnt+1);
}
public static boolean dis(int a,int b){
//判断两棵树圆心的距离是否小于两棵树的半径和
return (Math.pow(x[a]-x[b],2)+Math.pow(y[a]-y[b],2))<Math.pow(r[a]+r[b],2);
}
}