【蓝桥】植树

本文介绍了一个经典的植树问题,通过递归算法寻找在不使树木发生冲突的前提下,能够达到的最大覆盖面积。文章提供了一段Java代码实现,利用圆的几何特性判断树木间是否冲突,并采用递归方式尝试每一种可能的植树方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

小明和朋友们一起去郊外植树,他们带了一些在自己实验室精心研究出的小树苗。

小明和朋友们一共有 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

思路:

使用递归,种植最后一课树,记录种下的树的下标。计算面积。

image-20211219165238006

当没有下一棵树时,记录最大面积。

image-20211219165401189

判断已经种下的树同当前要种的树是否冲突,

image-20211219170023171

不冲突则继续记录,面积相加,取面积最大值。

若冲突则不种下。

往前依次类推…,选择种和不种最终取最大面积。

image-20211219164844192

完整代码

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);
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值