Luogu [P1378] 油滴扩展

首先,原题在这

恩,让我们进入正题:油滴扩展——显然,这道题是个搜索题,并且是个打眼一看上去就比较恶心的搜索题。

但是,这道题细节恶心,并不代表这道题思路难。

题意大家都了解了,让我们先来把细节问题坑点解决:

1.坐标范围为【-1000,1000】,有负数怎么办?

  解决方法很简单粗暴:将所有坐标加上1000就行了,然后就可视为所有坐标都为正数了。

2.让输出的答案为剩余的面积,还要四舍五入。

  解决方法也很简单:先搜索求出最大覆盖面积,然后将答案 + = 0.5 ,用矩形总面积减去答案输出即可。

然后就是代码实现部分,先声明变量:

int n; //n个油滴
int X1,Y1,X2,Y2;//矩形区域
double ans;//覆盖的最大面积 

int x[10],y[10];//编号为 [i] 的油滴的坐标
double r[10];   //编号为 [i] 的油滴的半径 

bool b[10]; //记录此油滴是否已经扩展 

//三个函数,感觉这样写可能会比 C++ 自带的快一些
inline double Max(double a,double b){
    return a > b ? a : b ;
}
inline double Min(double a,double b){
    return a < b ? a : b ;
}
inline int Abs(int a,int b){
    if(a>b)
        return a-b;
    return b-a;
}

然后就让我们进入真正的重点:搜索函数(代码里有详解哦~~)

void find(int now,double sum){//now 为将要搜第几个油滴 ,sum为现在已经扩展的面积
    if(now==n+1){//都搜完了
        ans=Max(ans,sum);//更新答案。
        return ;
    }

    for(int i=1;i<=n;i++)
        if(!b[i]){//若这个油滴还没被扩展 

            int tt=0;//临时变量 

            for(int j=1;j<=n;j++)//这个循环的作用是判断此油滴是否已经被其他油滴覆盖了
                if(b[j]&&r[j]>=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))){
                    tt=1;
                    b[i]=1;
                    find(now+1,sum);
                    b[i]=0;
                }

            if(tt==1)
                continue ;

            b[i]=1;

            r[i]=Min(Abs(x[i],X1),Abs(x[i],X2));
            r[i]=Min(r[i],Min(Abs(y[i],Y1),Abs(y[i],Y2)));//此油滴的可能半径为到边界的最短路径 

            for(int j=1;j<=n;j++)//根据已经扩展的油滴(j)半径来确定 此油滴(i)的最小半径
                if(i!=j&&b[j]){
                    double d=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
                    r[i]=Min(r[i],d-r[j]);
                }
            find(now+1,sum+pi*r[i]*r[i]);//寻找下一个油滴

            r[i]=0;//回溯
            b[i]=0;
        }
}

自此,本题重点就完啦。

下面是完整代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define pi 3.1415926
using namespace std;
int n; //n个油滴
int X1,Y1,X2,Y2;//矩形区域
double ans;//覆盖的最大面积 

int x[10],y[10];//编号为 [i] 的油滴的坐标
double r[10];   //编号为 [i] 的油滴的半径 

bool b[10]; //记录此油滴是否已经扩展 

//三个函数,感觉这样写可能会比 C++ 自带的快一些
inline double Max(double a,double b){
    return a > b ? a : b ;
}
inline double Min(double a,double b){
    return a < b ? a : b ;
}
inline int Abs(int a,int b){
    if(a>b)
        return a-b;
    return b-a;
}
void find(int now,double sum){//now 为将要搜第几个油滴 ,sum为现在已经扩展的面积
    if(now==n+1){//都搜完了
        ans=Max(ans,sum);//更新答案。
        return ;
    }

    for(int i=1;i<=n;i++)
        if(!b[i]){//若这个油滴还没被扩展 

            int tt=0;//临时变量 

            for(int j=1;j<=n;j++)//这个循环的作用是判断此油滴是否已经被其他油滴覆盖了
                if(b[j]&&r[j]>=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))){
                    tt=1;
                    b[i]=1;
                    find(now+1,sum);
                    b[i]=0;
                }

            if(tt==1)
                continue ;

            b[i]=1;

            r[i]=Min(Abs(x[i],X1),Abs(x[i],X2));
            r[i]=Min(r[i],Min(Abs(y[i],Y1),Abs(y[i],Y2)));//此油滴的可能半径为到边界的最短路径 

            for(int j=1;j<=n;j++)//根据已经扩展的油滴(j)半径来确定 此油滴(i)的最小半径
                if(i!=j&&b[j]){
                    double d=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
                    r[i]=Min(r[i],d-r[j]);
                }
            find(now+1,sum+pi*r[i]*r[i]);//寻找下一个油滴

            r[i]=0;//回溯
            b[i]=0;
        }

}
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){
        if(ch==‘-‘)
            f=-1;
        ch=getchar();
    }
    while(ch>=‘0‘&&ch<=‘9‘){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
int main(){
    n=read();
    X1=read()+1000,Y1=read()+1000,X2=read()+1000,Y2=read()+1000;
    for(int i=1;i<=n;i++)
        x[i]=read()+1000,y[i]=read()+1000;

    find(1,0.0);

    ans=Abs(X1,X2)*Abs(Y1,Y2)-ans;
    int answer=int(ans+0.5);
    printf("%d",answer);
    return 0;
}

原文地址:https://www.cnblogs.com/qiuchengrui/p/9785435.html

时间: 2024-12-19 12:09:10

Luogu [P1378] 油滴扩展的相关文章

P1378 油滴扩展

P1378 油滴扩展 题目描述 在一个长方形框子里,最多有N(0≤N≤6)个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界.必须等一个油滴扩展完毕才能放置下一个油滴.那么应该按照怎样的顺序在这N个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?(不同的油滴不会相互融合) 注:圆的面积公式V=pi*r*r,其中r为圆的半径. 输入输出格式 输入格式: 第1行一个整数N. 第2行为长方形边框一个顶点及其对角顶点的坐标,x,y,x’,y

洛谷 P1378 油滴扩展 改错

P1378 油滴扩展 题目描述 在一个长方形框子里,最多有\(N(0≤N≤6)\)个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界.必须等一个油滴扩展完毕才能放置下一个油滴.那么应该按照怎样的顺序在这\(N\)个点上放置油滴,才能使放置完毕后所有油滴占据的总面积最大呢?(不同的油滴不会相互融合) 输入输出格式 输入格式: 第1行一个整数N. 第2行为长方形边框一个顶点及其对角顶点的坐标,\(x,y,x',y'\). 接下去\(N\)行,每行

[洛谷P1378]油滴扩展

题目大意:有n滴油在一个平面上,油滴按顺序依次扩展(呈圆形),当碰到其他油滴或平面边界时停止扩展,让你设计一个扩展顺序,使平面剩余面积尽可能小. 解题思路:由于$n\leq 6$,我们可以dfs油滴扩展顺序,然后计算每个油滴能扩展的半径即可.时间复杂度$O(n!)$. 注意:①$\pi$的精度不能太小:②有些油滴包含在另一个油滴内部,则不能扩展:③题目要求四舍五入,则保留0位小数即可. 当然也可以用STL的全排列算法把所有排列求出来,然后按照排列顺序扩展. C++ Code: #include<

luogu cogs 油滴扩展

1076. [NOIP2010冲刺六] 油滴扩展 ★   输入文件:oilbox.in   输出文件:oilbox.out   简单对比 时间限制:1 s   内存限制:128 MB [题目描述] 在一个长方形框子里,最多有N(O≤N≤6)个相异的点.在其中任何一个点上放一个很小的油滴(即半径可视为0),那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界.必须等一个油滴扩展完毕才能放置下一个油滴.那么应该按照怎样的顺序在这N个点上放置油滴,才能使放置完毕后所有油滴占据的总面积最大呢?(不同

P1378 油滴扩展 - DFS

传送门 思路:由于n<=6,我们可以枚举油滴放置顺序的排列,然后DFS.对于每个油滴,其能扩散的最小半径为min{到四个边界的距离,到已添加的点的扩散范围的最小距离}.最后注意四舍五入:printf("%d",(int)ans+0.5);(其中ans为double类型). AC Code: #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> u

1378 油滴扩展

难度:普及+/提高 题目类型:搜索 提交次数:2 涉及知识:深搜 题目描述 在一个长方形框子里,最多有N(0≤N≤6)个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界.必须等一个油滴扩展完毕才能放置下一个油滴.那么应该按照怎样的顺序在这N个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?(不同的油滴不会相互融合) 注:圆的面积公式V=pi*r*r,其中r为圆的半径. 输入输出格式 输入格式: 第1行一个整数N. 第2行为长方形边框

[LG1378] 油滴扩展

暴力枚举油滴的编号的排列(next_permutation),然后按序一个一个扩展.面积的求最小值即可.也可以深搜. 复杂度 \(O(n!\times n^2)\). #include<cstdio> #include<algorithm> #include<cmath> #define sq(a) ((a)*(a)) #define PI 3.1415926535897932626 using namespace std; int n,l,r,u,d;//rtg in

油滴扩散

链接 未完待续 存代码用的 #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #define db double using namespace std; db a[100][3]={0},s,x,y,x1,yy; db r[1010],ans=0.0; int vis[1000101]={0},n; double dis(db xx,db yy,db xx1,db

刷题计划(暑假)

暂定每天更新. 7.7 1. P1378 油滴扩展 2. P1306 斐波那契公约数 3. Bugs Integrated, Inc.(加深理解三进制dp) 4. UVa12206 Stammering Aliens(复习字符串hash) 5. P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm 原文地址:https://www.cnblogs.com/wsmrxc/p/9275856.html