给m个雷达, n个城市, 以及每个城市的坐标, m个雷达里只能使用k个, 在k个雷达包围所有城市的前提下, 求最小半径。
先求出每个雷达到所有城市的距离, 然后二分半径, 如果距离小于二分的值, 就加边(大概不叫加边, 我也不知道叫什么......
#include<bits/stdc++.h> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair(x, y) #define lson l, m, rt<<1 #define mem(a) memset(a, 0, sizeof(a)) #define rson m+1, r, rt<<1|1 #define mem1(a) memset(a, -1, sizeof(a)) #define mem2(a) memset(a, 0x3f, sizeof(a)) #define rep(i, a, n) for(int i = a; i<n; i++) #define ull unsigned long long typedef pair<int, int> pll; const double PI = acos(-1.0); const double eps = 1e-8; const int mod = 1e9+7; const int inf = 1061109567; const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; const int maxn = 305; const int maxNode = 5000; struct node { int x, y; }a[51], b[51]; struct DLX { int L[maxNode], R[maxNode], U[maxNode], D[maxNode], row[maxNode], col[maxNode]; int S[maxn], H[maxn], deep, ans[maxn], sz, n, m, k; double g[52][52]; void remove(int c) { for(int i = D[c]; i!=c; i = D[i]) { L[R[i]] = L[i]; R[L[i]] = R[i]; } } void resume(int c) { for(int i = U[c]; i!=c; i = U[i]) { L[R[i]] = i; R[L[i]] = i; } } int h() { int cnt = 0; int vis[105]; mem(vis); for(int i = R[0]; i!=0; i = R[i]) { if(!vis[i]) { cnt++; vis[i] = 1; for(int j = D[i]; j!=i; j = D[j]) { for(int k = R[j]; k!=j; k = R[k]) { vis[col[k]] = 1; } } } } return cnt; } int dfs(int d) { if(d+h()>k) return 0; if(R[0] == 0) { return 1; } int c = R[0]; for(int i = R[0]; i!=0; i = R[i]) if(S[c]>S[i]) c = i; for(int i = D[c]; i!=c; i = D[i]) { remove(i); for(int j = R[i]; j!=i; j = R[j]) remove(j); if(dfs(d+1)) return 1; for(int j = L[i]; j!=i; j = L[j]) resume(j); resume(i); } return 0; } void add(int r, int c) { sz++; row[sz] = r; col[sz] = c; S[c]++; U[sz] = U[c]; D[sz] = c; D[U[c]] = sz; U[c] = sz; if(~H[r]) { R[sz] = H[r]; L[sz] = L[H[r]]; L[R[sz]] = sz; R[L[sz]] = sz; } else { H[r] = L[sz] = R[sz] = sz; } } void init(){ mem1(H); for(int i = 0; i<=n; i++) { R[i] = i+1; L[i] = i-1; U[i] = i; D[i] = i; } mem(S); R[n] = 0; L[0] = n; sz = n; } double dis(int i, int j) { return sqrt(1.0*(b[i].x-a[j].x)*(b[i].x-a[j].x)+(b[i].y-a[j].y)*(b[i].y-a[j].y)); } int check(double mid) { init(); for(int i = 1; i<=m; i++) { for(int j = 1; j<=n; j++) { if(mid-g[i][j]>=eps) { add(i, j); } } } if(dfs(0)) return 1; return 0; } void solve() { mem(g); for(int i = 1; i<=n; i++) scanf("%d%d", &a[i].x, &a[i].y); for(int i = 1; i<=m; i++) scanf("%d%d", &b[i].x, &b[i].y); for(int i = 1; i<=m; i++) { for(int j = 1; j<=n; j++) { g[i][j] = dis(i, j); } } double l = 0, r = 3000; while(r-l>eps) { double mid = (l+r)/2; if(check(mid)) r = mid; else l = mid; } printf("%.6f\n", l); } }dlx; int main() { int t; cin>>t; while(t--) { scanf("%d%d%d", &dlx.n, &dlx.m, &dlx.k); dlx.solve(); } return 0; }
原文:http://www.cnblogs.com/yohaha/p/5049606.html