HDU 3656 Fire station(巧妙的二分+DLX重复覆盖)
来源:互联网 发布:apache启动和停止命令 编辑:程序博客网 时间:2024/06/16 05:08
题目地址
题意:给你n个城市,在这个n个城市中要修m个消防局,问在这个限制条件下使得每一个城市发生火灾所需要的最大救援长度最短,最短为多少。
思路:和HDU 2295 Radar一样,但是我们这里就不能直接二分枚举距离了,我看别人博客学到了一个巧妙的二分方法,因为要求最短,那么最短肯定是恰好是某个城市到消防局的距离,所有我们把城市与城市之间的距离离散出来,这样的话我们二分搜索下标,这样的话二分的时间就缩短了。
#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <cmath>#include <cstdio>#include <algorithm>#include <iomanip>#define N 1010#define MAXSIZE 1010*1010#define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const LL mod = 1000000007;const double eps = 1e-8;struct node { int left, right, up, down, col, row;}mapp[MAXSIZE];int S[N], H[N];//S记录该列中1元素的个数int head, cnt;int len;int n, m;double lens[N][N], diss[N*N];//坑呀,居然忘记N*N了struct nope { double x, y;}A[N];struct Dancing_Links_X { void init() { head = 0; for (int i = 0; i <= n; i++) { S[i] = 0; mapp[i].up = mapp[i].down = i; mapp[i].left = (i == 0 ? n : i - 1); mapp[i].right = (i == n ? 0 : i + 1); } cnt = n; memset(H, -1, sizeof(H)); } void link(int x, int y) { cnt++; mapp[cnt].row = x; mapp[cnt].col = y; S[y]++; mapp[cnt].up = mapp[y].up; mapp[cnt].down = y; mapp[mapp[y].up].down = cnt; mapp[y].up = cnt; if (H[x] == -1) H[x] = mapp[cnt].left = mapp[cnt].right = cnt; else { mapp[cnt].left = mapp[H[x]].left; mapp[cnt].right = H[x]; mapp[mapp[H[x]].left].right = cnt; mapp[H[x]].left = cnt; } } void remove(int c) {//删去c这个点,以及关联的一列 for (int i = mapp[c].down; i != c; i = mapp[i].down) { mapp[mapp[i].left].right = mapp[i].right; mapp[mapp[i].right].left = mapp[i].left; } } void resume(int c) {//恢复c这个点,以及关联的一列 for (int i = mapp[c].up; i != c; i = mapp[i].up) { mapp[mapp[i].left].right = i; mapp[mapp[i].right].left = i; } } bool used[N]; int h() { int sum = 0; for (int i = mapp[head].right; i != head; i = mapp[i].right) used[i] = false; for (int i = mapp[head].right; i != head; i = mapp[i].right) { if (!used[i]) { sum++; used[i] = true; for (int j = mapp[i].down; j != i; j = mapp[j].down) for (int k = mapp[j].right; k != j; k = mapp[k].right) used[mapp[k].col] = true; } } return sum; } void dance(int nums) { if (nums + h() >= len) return; if (mapp[head].right == head) { len = min(len, nums); return; } int s = inf, c; for (int t = mapp[head].right; t != head; t = mapp[t].right) { if (S[t] < s) s = S[t], c = t; } for (int i = mapp[c].down; i != c; i = mapp[i].down) { remove(i); for (int j = mapp[i].right; j != i; j = mapp[j].right) { remove(j); } dance(nums + 1); for (int j = mapp[i].left; j != i; j = mapp[j].left) { resume(j); } resume(i); } return; }}DLX;double dis(int a, int b) { return sqrt((A[a].x - A[b].x)*(A[a].x - A[b].x) + (A[a].y - A[b].y)*(A[a].y - A[b].y));}bool solve(int mid) { DLX.init(); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (lens[i][j]<=diss[mid]) { DLX.link(j, i); } } } len = m + 1; DLX.dance(0); if (len > m) { return false; } return true;}int main() { int T; int size; scanf("%d", &T); while (T--) { size = 0; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%lf%lf", &A[i].x, &A[i].y); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { lens[i][j] = dis(i, j); diss[size++] = lens[i][j]; } } int l, r, mid, ans; sort(diss, diss + size); l = 0; r = unique(diss, diss + size) - diss - 1; while (r >= l) { mid = (l + r) / 2; if (solve(mid)) r = mid - 1, ans = mid; else l = mid + 1; } printf("%.6lf\n", diss[ans]); } return 0;}
阅读全文
0 0
- HDU 3656 Fire station(巧妙的二分+DLX重复覆盖)
- [DLX重复覆盖] hdu 3656 Fire station
- HDU 3656 Fire station DLX多重覆盖
- hdu3656Fire station(DLX重复覆盖 + 二分)
- [ACM] HDU 2295 Radar (二分+DLX 重复覆盖)
- [ACM] HDU 2295 Radar (二分+DLX 重复覆盖)
- HDU 2295 Radar (DLX可重复覆盖+二分)
- HDU 5046 Airport (DLX可重复覆盖+二分)
- HDU 2295 Radar(二分+DLX重复覆盖)
- HDU 5046 Airport(二分+DLX重复覆盖)
- hdu 2295 Radar(重复覆盖,二分+DLX)
- HDU 2295 Radar (二分+DLX,重复覆盖)
- HDU-5046 Airport(二分+DLX重复覆盖)
- HDU 3656 DLX重复覆盖
- HDU 2295 Radar(重复覆盖,DLX)
- hdu - 3498 - whosyourdaddy(重复覆盖DLX)
- HDU 5046 Airport(DLX重复覆盖)
- HDU 2828 Lamp(DLX重复覆盖)
- 《JavaScript高级程序设计》--Function类型笔记
- 1043. 输出PATest(20)
- Codeforces Gym 101485D Debugging
- c++继承和派生的理解
- Codeforces Round #437 (Div. 2 C. Ordering Pizza 贪心 only two types of pizza
- HDU 3656 Fire station(巧妙的二分+DLX重复覆盖)
- css 盒子模型理解
- 设计模式读书笔记-----迭代器模式
- 10.1日NOIP模拟赛
- 偏差与方差,欠拟合与过拟合
- 虚析构函数
- 设计模式
- Keyboard Row
- 分子量