洛谷 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
思路:一开始40分,后来改了好几次,没调出来,今天画了个图,就出来了。
所以最重要的还是数形结合。
错因:
if(sq<r[i])    R=0;
R=min(R,sq-r[i]);
 
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 7
using namespace std;
int n;
double r[MAXN];
double pi=3.1415926535;
int num[MAXN],vis[MAXN];
double ans=0x7f7f7f7f,x11,x22,y11,y22;
struct nond{
    double x,y;
}v[MAXN];
double ab(double x){
    return x>0?x:-x;
}
double work(int sum,double x,double y){
    double R=min(ab(x-x11),min(ab(x-x22),min(ab(y-y11),ab(y-y22))));
    for(int i=1;i<sum;i++){
        double sq=sqrt((x-v[num[i]].x)*(x-v[num[i]].x)+(y-v[num[i]].y)*(y-v[num[i]].y));
        if(sq<r[num[i]])    R=0;
        else R=min(R,sq-r[num[i]]);
    }
    return R;
}
void dfs(int tot,double sum){
    if(tot==n+1){
        if(sum<ans)    ans=sum;
        return ;
    }
    for(int i=1;i<=n;i++)
        if(!vis[i]){
            vis[i]=1;num[tot]=i;   
            r[i]=work(tot,v[i].x,v[i].y);
            dfs(tot+1,sum-pi*r[i]*r[i]);
            vis[i]=0;
        }
}
int main(){
    scanf("%d",&n);
    scanf("%lf%lf%lf%lf",&x11,&y11,&x22,&y22);
    for(int i=1;i<=n;i++)
        scanf("%lf%lf",&v[i].x,&v[i].y);
    dfs(1,ab(x11-x22)*ab(y11-y22));
    printf("%.0lf",ans);
}
/*
3 
-98 5 30 30
-42 11
-51 17
-11 22
2547
*/

 

 
posted @ 2018-04-01 09:08  一蓑烟雨任生平  阅读(201)  评论(0编辑  收藏  举报