洛谷P1378 油滴扩展

原题链接:https://www.luogu.com.cn/problem/P1378

P1378 油滴扩展

题目描述

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

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

输入格式

第1行一个整数N。

第2行为长方形边框一个顶点及其对角顶点的坐标,x,y,x’,y’。

接下去N行,每行两个整数xi,yi,表示盒子的N个点的坐标。

以上所有的数据都在[-1000,1000]内。

输出格式

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

输入输出样例

输入 #1   
2
20 0 10 10
13 3
17 7
输出 #1 
50


主要思路:
这是一道搜索题,因为n<=6,可以枚举所有的油滴放置顺序,计算油渍面积最大值再用总面积减去,得到答案。
首先与处理出任意两点之间的距离,然后在处理每个点与矩形四个边的最小距离。
然后搜索出所有的滴油顺序,求出面积。
每个油滴的扩展范围可以求出它到矩形边最小距离,与别的油滴之间距离减去那个油滴半径,这些值得最小一个即为此油滴的半径。

有几个要注意的地方:

1.一个油滴在另一个内部时不能扩展,即要把半径设为零不然有可能出现负数的半径。
2.四舍五入的是后c++不要直接int,要先加0.5,pascal应该用round();
3.如果不知道π是多少可以在c++中#include<math.h>然后按住Ctrl点击头文件名,在math.h中可以找到π的值。
                                
下面是代码:
c:
#include<stdio.h>
#include<math.h>
double a[7][7];
double sj[7][2];
double xx1,yy1,x2,y2,minn,anm=0;
double bl[7];
int n;
double abss(double kk){
    return kk>=0?kk:(-kk);}
void ss(int k){
    if(k==n){
        double s=0;
        for(int i=1;i<=n;i++)s+=bl[i]*bl[i];
        if(s>anm)anm=s;
        return;
    }
    for(int i=1;i<=n;i++)if(bl[i]==-1){
        double minm=a[i][0];
        for(int j=1;j<=n;j++)if(bl[j]!=-1)
            if(a[i][j]-bl[j]<minm)minm=a[i][j]-bl[j];
        if(minm<0)minm=0;
        bl[i]=minm;
        ss(k+1);
        bl[i]=-1;
    }
    return;}
int main(){
    for(int i=0;i<=6;i++)bl[i]=-1;
    scanf("%d%lf%lf%lf%lf",&n,&xx1,&yy1,&x2,&y2);
    for(int i=1;i<=n;i++)scanf("%lf%lf",&sj[i][0],&sj[i][1]);
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
        a[i][j]=a[j][i]=sqrt((sj[i][0]-sj[j][0])*(sj[i][0]-sj[j][0])+(sj[i][1]-sj[j][1])*(sj[i][1]-sj[j][1]));
    for(int i=1;i<=n;i++){
        minn=abss(sj[i][0]-xx1);
        if(abss(sj[i][0]-x2)<minn)minn=abss(sj[i][0]-x2);
        if(abss(sj[i][1]-yy1)<minn)minn=abss(sj[i][1]-yy1);
        if(abss(sj[i][1]-y2)<minn)minn=abss(sj[i][1]-y2);
        a[i][0]=a[0][i]=minn;
    }
    ss(0);
    double h=anm*3.14159265358979323846;
    double s1=abss(x2-xx1)*abss(y2-yy1);
    int zj=(int)(s1-h+0.5); 
    printf("%d",zj);
    return 0;}

pascal:

var
    a:array[0..7,0..7]of real;
    sj:array[0..7,0..2]of real;
    bl:array[0..7]of real;
    xx1,yy1,x2,y2,minn,anm,h,s1:real;
    n,zj:longint;
function abss(kk:real):real;
begin
    if kk>=0 then exit(kk)
    else exit(kk*(-1));
end;
procedure ss(k:longint);
var
    s,minm:real;
    i1,j1:longint;
begin
    if k=n then begin
        s:=0;
        for i1:=1 to n do s:=s+(bl[i1]*bl[i1]);
        if s>anm then anm:=s;
        exit();
    end;
    for i1:=1 to n do begin
        if bl[i1]=-1then begin
            minm:=a[i1,0];
            for j1:=1 to n do
                if (bl[j1]<>-1) and ((a[i1,j1]-bl[j1])<minm) then
                    minm:=a[i1,j1]-bl[j1];
                if minm<0 then minm:=0;
                bl[i1]:=minm;
                ss(k+1);
                bl[i1]:=-1;
        end;
    end;
    exit();
end;
var
    i,j:longint;
begin
    anm:=0;
    for i:=1 to 6 do bl[i]:=-1;
    readln(n);
    readln(xx1,yy1,x2,y2);
    for i:=1 to n do read(sj[i,0],sj[i,1]);
    for i:=1 to n do for j:=1 to n do begin
        a[j,i]:=sqrt((sj[i,0]-sj[j,0])*(sj[i,0]-sj[j,0])+(sj[i,1]-sj[j,1])*(sj[i,1]-sj[j,1]));
        a[i,j]:=a[j,i];
    end;
    for i:=1 to n do begin
        minn:=abss(sj[i,0]-xx1);
        if abss(sj[i,0]-x2)<minn then minn:=abss(sj[i,0]-x2);
        if abss(sj[i,1]-yy1)<minn then minn:=abss(sj[i,1]-yy1);
        if abss(sj[i,1]-y2)<minn then minn:=abss(sj[i,1]-y2);
        a[i,0]:=minn;
        a[0,i]:=minn;
    end;
    ss(0);
    h:=anm*3.14159265358979323846;
    s1:=abss(x2-xx1)*abss(y2-yy1);
    zj:=round(s1-h);
    writeln(zj);
end.

 如果有什么问题,请指出,谢谢。





 

posted @ 2020-02-24 21:28  __int128  阅读(176)  评论(0编辑  收藏  举报