P1378 油滴扩展
Posted garen-wang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1378 油滴扩展相关的知识,希望对你有一定的参考价值。
思路不难,但是实现过程还是错了。。。
给这道题的几个点补充一下:
可以按照顺序滴下这些油滴。
滴油滴的过程,是以滴下的点为圆心,向四周扩展出最大的半径。图形一定是个圆。
油滴碰到边界就停止流。
因为用圆表示,所以你绝对不可能弄个数组模拟!我真的菜!
我最开始的时候还想着把坐标平移,结果没必要。。。
因为(0 leq N leq 6),所以弄个全排列是松松的。这道题就要用到全排列
滴入一个点的时候,我们就需要计算半径,并且记录下这个半径。前面的圆的半径会对后面的起限制作用。
那么问题来了:如何计算半径?
我们得到一个点的圆心后,就与上下左右横纵坐标限制一下。注意得到的是半径而不是直径。
然后就对前面的圆来做限制。
注意:我们要滴的点可能在先前的圆内或圆上或圆外。
当点在圆内,那么这个点的半径直接就为0,因为这些油滴不能相互溶解。
当点在圆上的时候半径还是0。
当点在圆外的时候,由数学必修2的知识,可以求出两个圆心的距离,然后减去先前圆的半径,得到的长度再与答案取min。
其他的就是基本操作了。
代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
const int maxn = 10;
const double pi = 3.1415926535897932384626434;
int n;
double x[maxn], y[maxn];
double minx, miny, maxx, maxy;
double ans;
bool vis[maxn];
double r[maxn];
double solve(int z)
{
double temp1 = std::min(fabs(x[z] - minx), fabs(maxx - x[z]));
double temp2 = std::min(fabs(y[z] - miny), fabs(maxy - y[z]));
double res = std::min(temp1, temp2);
for(int i = 1; i <= n; i++)
{
if(i != z && vis[i])
{
double d = sqrt((x[z] - x[i]) * (x[z] - x[i]) + (y[z] - y[i]) * (y[z] - y[i]));
res = std::min(res, std::max(d - r[i], 0.0));
}
}
return res;
}
void dfs(int t, double res)
{
if(t == n + 1)
{
ans = std::max(ans, res);
return;
}
for(int i = 1; i <= n; i++)
{
if(!vis[i])
{
vis[i] = true;
r[i] = solve(i);
dfs(t + 1, res + pi * r[i] * r[i]);
r[i] = 0;
vis[i] = false;
}
}
}
int main()
{
scanf("%d", &n);
scanf("%lf%lf%lf%lf", &minx, &miny, &maxx, &maxy);
if(minx > maxx) std::swap(minx, maxx);
if(miny > maxy) std::swap(miny, maxy);
for(int i = 1; i <= n; i++) scanf("%lf%lf", &x[i], &y[i]);
dfs(1, 0.0);
printf("%.0lf
", (maxx - minx) * (maxy - miny) - ans);
return 0;
}
以上是关于P1378 油滴扩展的主要内容,如果未能解决你的问题,请参考以下文章