luogu1378 油滴扩展 (深搜)

这道题目的方法并不难想,但能做到一遍AC的也一定是真dalao.

题目大意:

    1.一块长方形板上有n个点,可以往n个点上滴油。

    2.油会扩散开来直到碰到长方形边或其他油滴(油滴为圆形),求不同的滴油方案最小剩余的长方形板的面积。

解题思路:

    1.n只有6,可以深搜求出所有滴油的次序,就是全排列。

    2.然后求出面积,取个最大的。

细节:

    1.如果油滴碰到其他点还是会扩散的,而这些点上再滴油就不会扩展了。

    2.记得是剩余的面积,本蒟蒻搞了半天发现题目看错了。

上代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>

#define rep(x, l, r) for (int x = l; x <= r; x++)
#define repd(x, r, l) for (int x = r; x >= l; x--)
#define clr(x, y) memset(x, y, sizeof(x))
#define sqr(x) (x) * (x)
#define MAXN 15
#define INF 1 << 30
typedef long long LL;
using namespace std;
const double pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679;//这个π有点……

struct node
{
    int x, y;
} a[MAXN];
int n;
double ans;
double sze[MAXN], g[MAXN];
int b[MAXN];
bool flag[MAXN];

double dis(int i, int j)//求i到j的距离
{
    return sqrt(sqr(a[i].x - a[j].x) + sqr(a[i].y - a[j].y));
}

void dfs(int t)
{
    if (t > n)
    {
        double sum = 0;
        clr(sze, 0);
        rep(i, 1, n)
        {
            int u = b[i];
            double s = g[u];
            rep(j, 1, n)
            {
                if (sze[j])//如果这个位置滴过油
                {
                    s = min(s, dis(u, j) - sze[j]);
                }
            }
            if (s < 0)//这个点已经被其他点扩散了
                s = 0;
            sze[u] = s;
            sum += s * s * pi;
        }
        ans = max(ans, sum);
        return;
    }
    rep(i, 1, n)
    {
        if (!flag[i])
        {
            flag[i] = 1;
            b[t] = i;
            dfs(t + 1);
            flag[i] = 0;
        }
    }
}

int main()
{
    scanf("%d", &n);
    int x0, y0, x1, y1;
    scanf("%d%d%d%d", &x0, &y0, &x1, &y1);
    if (x0 > x1)
        swap(x0, x1);
    if (y0 > y1)
        swap(y0, y1);
    rep(i, 1, n)
    {
        scanf("%d%d", &a[i].x, &a[i].y);
        g[i] = min(a[i].x - x0, min(x1 - a[i].x, min(a[i].y - y0, y1 - a[i].y)));//g[i]表示i点到最近的边的距离
    }
    dfs(1);
    printf("%d\n", (x1 - x0) * (y1 - y0) - (int)(ans + 0.5));
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值