zoukankan      html  css  js  c++  java
  • 洛谷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.

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





  • 相关阅读:
    SSH入门常用命令
    Charles基础
    经典测试用例
    Fiddler基础教程
    增、删、改、查
    一位软件测试工程师浅谈用户体验
    用户体验测试点
    IIS测试环境搭建
    禅道Bug管理工具环境搭建
    LineageOS源码定制手机系统
  • 原文地址:https://www.cnblogs.com/sy666/p/12327537.html
Copyright © 2011-2022 走看看