P1378 油滴扩展
作者:互联网
暴力出全排列然后求出这种放油的顺序得到的覆盖面积,求所有覆盖面积的最大值,实际做的时候ans保存的是所有半径的平方的和的最大值。
在放一个油滴A的时候,需要和之前放下的油滴B一一比较,如果A和B的距离小于B的半径,那么放不了,否则可能的半径为\(r(A)=dist(A, B)-r(B)\),和所有点比较后,取最小的r(A),然后还需要用r(A)和A离矩形边框四周的距离取一遍最小,这样就得到了真正的r(A)
另外这题的PI的精确度会影响结果,开始用的3.14, 后来改用系统宏M_PI过了
#include<iostream>
#include<cmath>
using namespace std;
const int N = 10;
#define PII pair<int, int>
#define x first
#define y second
int n;
int down_, up_, left_, right_;
PII p[N];
double r[N]; // 半径
int path[N];
double ans;
int st[N];
double dist(PII a, PII b){
double dx = a.x - b.x;
double dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
void dfs(int u){
if(u == n){
for(int i = 0; i < n; i ++){
double minv = 1e9;
for(int j = 0; j < i; j ++){
double d = dist(p[path[i]], p[path[j]]);
if(d < r[path[j]]){
minv = 0;
break;
}
minv = min(minv, d - r[path[j]]);
}
minv = min(minv, fabs(p[path[i]].x - left_));
minv = min(minv, fabs(p[path[i]].x - right_));
minv = min(minv, fabs(p[path[i]].y - up_));
minv = min(minv, fabs(p[path[i]].y - down_));
r[path[i]] = minv;
}
double maxv = 0;
for(int i = 0; i < n; i ++) maxv = maxv + r[i] * r[i];
ans = max(ans, maxv);
return;
}
for(int i = 0; i < n; i ++){
if(st[i] == 0){
st[i] = 1;
path[u] = i;
dfs(u + 1);
st[i] = 0;
}
}
}
int main(){
cin >> n;
int a, b, c, d;
cin >> a >> b >> c >> d;
left_ = min(a, c);
right_ = max(a, c);
up_ = max(b, d);
down_ = min(b, d);
for(int i = 0; i < n; i ++)
cin >> p[i].x >> p[i].y;
dfs(0);
printf("%.0lf", (up_ - down_) * (right_ - left_) - M_PI * ans);
return 0;
}
标签:min,P1378,double,扩展,++,int,path,油滴,minv 来源: https://www.cnblogs.com/tomori/p/15342504.html