HDU 2295 Radar【二分+Dancing Links重复覆盖】
来源:互联网 发布:js给图片加边框 编辑:程序博客网 时间:2024/06/16 11:20
重复覆盖不同于精确覆盖,要求是在0/1矩阵中选择最少的行使每一列至少有一个1。进行重复覆盖时要使用估价函数来剪枝。
这题二分雷达半径,找到能将所有城市覆盖的最小半径即可。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath> using namespace std;const int maxn = 50*50 + 10;const int oo = 1 << 30;const int maxrow = 55;const int maxcol = 55;int mtx[maxrow][maxcol];double dis[55][55];double cx[55], cy[55];double rx[55], ry[55];int t, n, m, k;int totRow, totCol, head, idx;int L[maxn], R[maxn], U[maxn], D[maxn];int RH[maxn], CH[maxn], S[maxn];void initMtx(double x){ memset(mtx, 0, sizeof(mtx)); for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (dis[i][j] <= x) { mtx[i][j] = 1; } } }}int newNode(int up, int down, int left, int right){ U[idx] = up; D[idx] = down; L[idx] = left; R[idx] = right; U[down] = D[up] = L[right] = R[left] = idx; return idx++;}void build(){ idx = maxn - 1; head = newNode(idx, idx, idx, idx); idx = 0; for (int j = 0; j < totCol; ++j) { newNode(idx, idx, L[head], head); CH[j] = j; S[j] = 0; } for (int i = 0; i < totRow; ++i) { int k = -1; for (int j = 0; j < totCol; ++j) { if (!mtx[i][j]) continue; if (-1 == k) { k = newNode(U[CH[j]], CH[j], idx, idx); RH[k] = i; CH[k] = j; S[j]++; } else { k = newNode(U[CH[j]], CH[j], k, R[k]); RH[k] = i; CH[k] = j; S[j]++; } } }}void remove(int c){ for (int i = D[c]; i != c; i = D[i]) { L[R[i]] = L[i]; R[L[i]] = R[i]; /*S[CH[i]]--;*/ }}void resume(int c){ for (int i = U[c]; i != c; i = U[i]) { L[R[i]] = R[L[i]] = i; /*S[CH[i]]++;*/ }}/*估价函数*/int h(){ bool vis[maxcol]; memset(vis, false, sizeof(vis)); int ret = 0; for (int i = R[head]; i != head; i = R[i]) { if (!vis[i]) { ret++; vis[i] = true; for (int j = D[i]; j != i; j = D[j]) { for (int k = R[j]; k != j; k = R[k]) { vis[CH[k]] = true; } } } } return ret;}bool dance(int cnt){ if (cnt + h() > k) { return false; } if (R[head] == head) { return true; } int c, Min = oo; for (int i = R[head]; i != head; i = R[i]) { if (S[i] < Min) { Min = 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 (dance(cnt + 1)) { return 1; } for (int j = L[i]; j != i; j = L[j]) { resume(j); } resume(i); } return false; }int main(){ scanf("%d", &t); while (t--) { scanf("%d%d%d", &n, &m, &k); totRow = m; totCol = n; for (int i = 0; i < n; ++i) { scanf("%lf%lf", &cx[i], &cy[i]); } for (int i = 0; i < m; ++i) { scanf("%lf%lf", &rx[i], &ry[i]); } double l = 1e9, r = -1.0; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { dis[i][j] = sqrt((rx[i] - cx[j])*(rx[i] - cx[j]) + (ry[i] - cy[j])*(ry[i] - cy[j])); l = min(dis[i][j], l); r = max(dis[i][j], r); } } while (r - l > 1e-7) { double mid = (r + l) / 2.0; initMtx(mid); build(); if (dance(0)) { r = mid; } else { l = mid; } } printf("%.6lf\n", l); } return 0;}
- HDU 2295 Radar【二分+Dancing Links重复覆盖】
- HDU 2295 Radar( 二分+Dancing Links重复覆盖 )
- hdu 2295 Radar(Dancing Links重复覆盖)
- HDU 2295 Radar(重复覆盖|Dancing Links)
- Hdu 2295 (二分+重复覆盖问题 Dancing Links)
- hdu 2295 dancing links 求重复覆盖
- HDU2295 Radar —— Dancing Links 可重复覆盖
- hdu 2295 Radar(重复覆盖,二分+DLX)
- 【HDU】2295 Radar 二分+重复覆盖
- HDU 2295 Radar (二分+DLX,重复覆盖)
- HDU 2295 Radar(二分+重复覆盖)
- hdu 3335 Divisibility(Dancing Links重复覆盖)
- HDU 3498 whosyourdaddy【Dancing Links重复覆盖】
- HDU 5046 Airport ( Dancing Links 重复覆盖 )
- hdu2295Radar [dancing links重复覆盖]
- [ACM] HDU 2295 Radar (二分+DLX 重复覆盖)
- [ACM] HDU 2295 Radar (二分+DLX 重复覆盖)
- HDU 2295 Radar (DLX可重复覆盖+二分)
- Java程序员应该知道的10个调试技巧
- Cotex-A8开发板之Telnet移植
- s3c6410 + wince6.0 内核中修改LCD尺寸进度条
- CentOS5命令
- 黑马程序员之WinForm编程基础学习笔记:简单的四则运算器
- HDU 2295 Radar【二分+Dancing Links重复覆盖】
- 那些争议最大的编程观点
- DomHelper
- 黑马程序员之WinForm编程基础学习笔记:省市选择器
- [開發記錄] 函式庫調用 - 使用C6accel 資料庫進行FFT函式調用 之其一
- 黑马程序员之WinForm编程基础学习笔记:日月选择器,假设2月份总是28天。1,3,4,7,8,10,12月份是31天,其他是30天。
- java.util下的Timer,TimerTask和quartz的比较
- Qt基础——Qt4.7安装 windows7+Qt+VS2008
- strftime