HDU

来源:互联网 发布:php富文本编辑器 编辑:程序博客网 时间:2024/04/30 14:26

题意:

给出n个点,要求在其中找到k个点,使得任意两个点的最短距离最大。

思路:

最大化最小值,很明显要二分答案判断是否可行,关键是判断可行的方案,直接对于这n个点求一个最大团,这个团满足任意两个点的距离都要大于等于当前二分的答案,看这样求出的最大团的大小是否大于等于k。

代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>using namespace std;const int MAXN = 55;const int INF = 0x3f3f3f3f;struct MaxClique {double g[MAXN][MAXN];int n, ans, dp[MAXN], st[MAXN][MAXN];void init(int n) {this->n = n;}void addedge(int u, int v, double w) {g[u][v] = w;}bool dfs(int sz, int num, double w) {if (sz == 0) {if (num > ans) {ans = num;return true;}return false;}for (int i = 0; i < sz; i++) {if (sz - i + num <= ans) return false;int u = st[num][i];if (dp[u] + num <= ans) return false;int cnt = 0;for (int j = i + 1; j < sz; j++) {if (g[u][st[num][j]] >= w) st[num + 1][cnt++] = st[num][j];}if (dfs(cnt, num + 1, w)) return true;}return false;}int solve(double w) {ans = 0;memset(dp, 0, sizeof(dp));for (int i = n; i >= 1; i--) {int cnt = 0;for (int j = i + 1; j <= n; j++) {if (g[i][j] >= w) st[1][cnt++] = j;}dfs(cnt, 1, w);dp[i] = ans;}return ans;}} maxclique;double binsearch(double l, double r, int k) {for (int i = 1; i <= 50; i++) {double m = (l + r) / 2.0;if (maxclique.solve(m) >= k) l = m;else r = m;}return l;}struct Point {double x, y;} p[MAXN]; double dis(Point a, Point b) {return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); }int main() {int n, m;while (scanf("%d%d", &n, &m) == 2) {for (int i = 1; i <= n; i++) {scanf("%lf%lf", &p[i].x, &p[i].y);}maxclique.init(n);double l = INF, r = 0;for (int i = 1; i <= n; i++) {for (int j = i + 1; j <= n; j++) {double d = dis(p[i], p[j]);maxclique.addedge(i, j, d);maxclique.addedge(j, i, d);r = max(r, d);l = min(l, d);}}printf("%.2f\n", binsearch(l, r, m));}return 0; }

0 0