这道题目的方法并不难想,但能做到一遍AC的也一定是真dalao.
题目大意:
1.一块长方形板上有n个点,可以往n个点上滴油。
2.油会扩散开来直到碰到长方形边或其他油滴(油滴为圆形),求不同的滴油方案最小剩余的长方形板的面积。
解题思路:
1.n只有6,可以深搜求出所有滴油的次序,就是全排列。
2.然后求出面积,取个最大的。
细节:
1.如果油滴碰到其他点还是会扩散的,而这些点上再滴油就不会扩展了。
2.记得是剩余的面积,本蒟蒻搞了半天发现题目看错了。
上代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define rep(x, l, r) for (int x = l; x <= r; x++)
#define repd(x, r, l) for (int x = r; x >= l; x--)
#define clr(x, y) memset(x, y, sizeof(x))
#define sqr(x) (x) * (x)
#define MAXN 15
#define INF 1 << 30
typedef long long LL;
using namespace std;
const double pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679;//这个π有点……
struct node
{
int x, y;
} a[MAXN];
int n;
double ans;
double sze[MAXN], g[MAXN];
int b[MAXN];
bool flag[MAXN];
double dis(int i, int j)//求i到j的距离
{
return sqrt(sqr(a[i].x - a[j].x) + sqr(a[i].y - a[j].y));
}
void dfs(int t)
{
if (t > n)
{
double sum = 0;
clr(sze, 0);
rep(i, 1, n)
{
int u = b[i];
double s = g[u];
rep(j, 1, n)
{
if (sze[j])//如果这个位置滴过油
{
s = min(s, dis(u, j) - sze[j]);
}
}
if (s < 0)//这个点已经被其他点扩散了
s = 0;
sze[u] = s;
sum += s * s * pi;
}
ans = max(ans, sum);
return;
}
rep(i, 1, n)
{
if (!flag[i])
{
flag[i] = 1;
b[t] = i;
dfs(t + 1);
flag[i] = 0;
}
}
}
int main()
{
scanf("%d", &n);
int x0, y0, x1, y1;
scanf("%d%d%d%d", &x0, &y0, &x1, &y1);
if (x0 > x1)
swap(x0, x1);
if (y0 > y1)
swap(y0, y1);
rep(i, 1, n)
{
scanf("%d%d", &a[i].x, &a[i].y);
g[i] = min(a[i].x - x0, min(x1 - a[i].x, min(a[i].y - y0, y1 - a[i].y)));//g[i]表示i点到最近的边的距离
}
dfs(1);
printf("%d\n", (x1 - x0) * (y1 - y0) - (int)(ans + 0.5));
return 0;
}