<洛谷>P1378 油滴拓展

35 篇文章 2 订阅

题目描述

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

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

输入格式

第一行,一个整数 NN。

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

接下来 NN 行,第 ii 行两个整数 x_i, y_ixi​,yi​,表示盒子内第 ii 个点的坐标。

输出格式

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

说明/提示

对于 100\%100% 的数据,1 \le N \le 61≤N≤6,坐标范围在 [-1000, 1000][−1000,1000] 内。

AC代码如下:

#include<cstdio>
#include<cmath>
#define PI 3.1415926
using namespace std;

int n, tag[7];//用来标记点
double A[7][2], x, y, x2, y2, R[7], max, dis[7][7];
//R用来标记半径 A用来存储坐标 dis存储点的距离

double abss(double a) //定义一个给浮点数取绝对值的函数
{
    return a > 0.0 ? a : -a;
}

void dfs(int step, double s)
{//准备放置第step个油滴,放置前面积为s
    int k, i;
    double r = 0;//准备放置的油滴的扩散半径

    if (step == n + 1)//放完
        max = s > max ? s : max;
    else
        for (k = 1; k <= n; k++)
            if (!tag[k])//标记
        {
            //矩形和已放置的油滴约束了r的大小
            r = abss(y2 - A[k][1]);//到水平墙面的距离

            if (r > abss(x2 - A[k][0]))
                r = abss(x2 - A[k][0]);//到竖直墙面的距离
            if (r > abss(y - A[k][1]))
                r = abss(y - A[k][1]);//..
            if (r > abss(x - A[k][0]))
                r = abss(x - A[k][0]);//.
            //做法的解释:找出点离哪面墙最近 确定最小的半径

            for (i = 1; i <= n; i++)
                if (tag[i])//如果这个点有油滴
                if (r > dis[k][i] - R[i]) //继续判断 如果r比两个油滴之间的距离减去另一个
                    r = dis[k][i] - R[i];//的扩散半径还大 那么他最多只能扩散两个油滴之间的
            //距离减去另一个油滴的扩散半径
            r = r < 0 ? 0 : r;//注意r不能为负
            //R为负的情况就是 一个油滴已经覆盖了没有滴的油滴

            tag[k] = 1; R[k] = r;
            dfs(step + 1, s + PI * r * r);//在下层dfs时 把面积传入下层
            tag[k] = 0; R[k] = 0.0;//返回上层 解除标记 并且让半径恢复0
        }
}

int main(void)
{
    int i, j;
    scanf("%d%lf%lf%lf%lf", &n, &x, &y, &x2, &y2);

    for (i = 1; i <= n; i++)
        scanf("%lf%lf", &A[i][0], &A[i][1]);

    //预处理出油滴间距dis
    for (i = 1; i <= n; i++)
        for (j = 1; j < i; j++)
            if (i != j)
        dis[i][j] = dis[j][i] = sqrt((A[i][0] - A[j][0]) * (A[i][0] - A[j][0])
            +
            (A[i][1] - A[j][1]) * (A[i][1] - A[j][1]));

    dfs(1, 0.0);

    double S = abss(x - x2) * abss(y - y2);//矩形面积
    printf("%.0lf", S - max);

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值