油滴拓展(dfs)

题目描述

在一个长方形框子里,最多有 N 个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。那么应该按照怎样的顺序在这 N 个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?(不同的油滴不会相互融合)

注:圆的面积公式 V=πr2,其中 r 为圆的半径。

输入格式

第一行,一个整数 N。

第二行,四个整数 x,y,x′,y′,表示长方形边框一个顶点及其对角顶点的坐标。

接下来 N 行,第 i 行两个整数 ixi​,yi​,表示盒子内第 i 个点的坐标。

输出格式

一行,一个整数,长方形盒子剩余的最小空间(结果四舍五入输出)。

此题目的思路比较简单,但是细节比较多。首先是计算油滴所占面积的问题,我们计算每滴油的半径要取圆心于长方形框的四条边的距离以及与其他圆距离的最小值(与其他油滴的距离的计算方式是两个圆心的距离减去另一个圆的半径,需要注意的是一旦两个圆的距离小于零就说明此油滴被另一个油滴包含了)。其次是题目所有数据用double存储,为了保证结果的准确性,尽量把Π往后多写几位,结果的四舍五入用round函数即可。

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
bool vis[30];
double n,x,y,dx,dy,ans=0,s,r[30];
double pai=3.1415926535;
struct node{
    double x,y;
}q[30];//存储每个点的坐标
double findr(int i)计算此点油滴 的半径
{
    double minr;
    double r1=min(abs(q[i].x-x),abs(q[i].x-dx));
    double r2=min(abs(q[i].y-y),abs(q[i].y-dy));
    minr=min(r1,r2);//取离边界最近的距离
    for(int j=0;j<n;j++)
    {
        if(i!=j&&vis[j])
        {
            double rr;
            rr=sqrt((q[i].x-q[j].x)*(q[i].x-q[j].x)+(q[i].y-q[j].y)*(q[i].y-q[j].y))-r[j];//与另一个圆的距离
            if(rr>=0)
                minr=min(rr,minr);
            else
                minr=0;
        }
    }
    return minr;
}
void dfs(int m,double sum)
{
    if(m==n)
    {
        ans=max(ans,sum);
        return ;
    }
    for(int i=0;i<n;i++)
    {
        if(!vis[i])
        {
            vis[i]=true;
            r[i]=findr(i);
            dfs(m+1,sum+r[i]*r[i]*pai);
            vis[i]=false;
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>x>>y>>dx>>dy;
    for(int i=0;i<n;i++)
        cin>>q[i].x>>q[i].y;
    s=abs((x-dx)*(y-dy));
    dfs(0,0);
    double v=s-ans;//剩余面积的最小值就是边框面积减去油滴面积的最大值
    cout<<(int)round(v)<<endl;
    return 0;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值