题意:

  N个城市,M个雷达站,K个操作员,问雷达的半径至少为多大,才能覆盖所有城市。M个雷达中最多只能有K个同时工作。

思路:

  二分雷达的半径,看每个雷达可以覆盖哪些城市,然后做重复覆盖,判断这个半径是否可行。

  我是直接二分的半径,跑了300+ms,看了Virtual Judge上面跑得快的代码,才发现为了不浪费半径的长度,最小的半径一定等于某一个雷达站到某一个城市之间的距离。这样一来枚举量就小了很多,只需要15ms……

代码:

  300+ms的 -_-

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <cctype>
#include <time.h> using namespace std; const double eps = 1e-;
const int INF = <<;
const int MAXN = ;
const int MAXR = ;
const int MAXNODE = MAXN*MAXR; struct DLX {
// 行编号从1开始,列编号为1~n,结点0是表头结点;结点1~n是各列顶部的虚拟结点
int n, sz; // 列数,结点总数
int S[MAXN]; //各列结点数 int row[MAXNODE], col[MAXNODE]; //各结点行列编号
int L[MAXNODE], R[MAXNODE], U[MAXNODE], D[MAXNODE]; //十字链表 int ansd, ans[MAXR]; // 解 void init(int n) { //n是列数
this->n = n; //虚拟结点
for (int i = ; i <= n; i++) {
U[i] = i; D[i] = i; L[i] = i-; R[i] = i+;
}
R[n] = ; L[] = n;
sz = n+;
memset(S, , sizeof(S));
} void addRow(int r, vector<int> columns) {
//这一行的第一个结点
//行没有设头结点,每一行连成一个环形
int first = sz;
for (int i = ; i < columns.size(); i++) {
int c = columns[i];
L[sz] = sz-; R[sz] = sz+; D[sz] = c; U[sz] = U[c];
D[U[c]] = sz; U[c] = sz;
row[sz] = r; col[sz] = c;
S[c]++; sz++;
}
R[sz-] = first; L[first] = sz-;
} //顺着链表A,遍历s外的其他元素
#define FOR(i, A, s) for (int i = A[s]; i != s; i = A[i]) void remove(int c) { //删除c列
FOR(i, D, c) {
L[R[i]] = L[i]; R[L[i]] = R[i];
}
} void restore(int c) { //回连c列
FOR(i, U, c) {
L[R[i]] = R[L[i]] = i;
}
} bool vis[MAXN]; int f() {
int ret = ;
FOR(c, R, ) vis[c] = true;
FOR(c, R, ) if (vis[c]) {
ret++; vis[c] = false;
FOR(i, D, c) FOR(j, R, i)
vis[col[j]] = false;
}
return ret;
} void dfs(int d) { //d为递归深度
if (d+f()>=ansd) return ;
if (R[] == ) { //找到解
ansd = min(ansd, d); //记录解的长度
return ;
} //找S最小的C列
int c = R[]; //第一个未删除的列
for (int i = R[]; i != ; i = R[i]) if (S[i]<S[c]) c = i; for (int i = D[c]; i != c; i = D[i]) { //用结点i所在的行覆盖第c列
remove(i);
for (int j = R[i]; j != i; j = R[j]) remove(j); //删除节结点i所在行覆盖第c列
ans[d] = row[i];
dfs(d+);
for (int j = L[i]; j != i; j = L[j]) restore(j); // 恢复
restore(i);
}
} int solve() {
ansd = INF;
dfs();
return ansd;
}
}; DLX solver;
vector<int> columns; int n, m, k;
double a[MAXN][];
double b[MAXN][];
double G[MAXN][MAXN]; int check(double x) {
solver.init(n);
for (int i = ; i < m; i++) {
columns.clear();
for (int j = ; j < n; j++) if (G[i][j]<=x)
columns.push_back(j+);
if (!columns.empty()) solver.addRow(i+, columns);
}
return solver.solve();
} int main() {
#ifdef Phantom01
freopen("HDU2295.txt", "r", stdin);
#endif //Phantom01 int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d%d", &n, &m, &k);
for (int i = ; i < n; i++)
scanf("%lf%lf", &a[i][], &a[i][]);
for (int i = ; i < m; i++)
scanf("%lf%lf", &b[i][], &b[i][]);
double l = , r = , mm;
for (int i = ; i < m; i++) {
for (int j = ; j < n; j++) {
G[i][j] = sqrt((b[i][]-a[j][])*(b[i][]-a[j][]) + (b[i][]-a[j][])*(b[i][]-a[j][]));
r = max(r, G[i][j]);
}
}
while (abs(r-l)>eps) {
mm = (l+r)/;
if (check(mm)>k) l = mm;
else r = mm;
}
printf("%.6f\n", r+eps);
} return ;
}

HDU 2295 Radar 重复覆盖 DLX的更多相关文章

  1. hdu 2295 Radar 重复覆盖+二分

    题目链接 给m个雷达, n个城市, 以及每个城市的坐标, m个雷达里只能使用k个, 在k个雷达包围所有城市的前提下, 求最小半径. 先求出每个雷达到所有城市的距离, 然后二分半径, 如果距离小于二分的 ...

  2. HDU 2295.Radar (DLX重复覆盖)

    2分答案+DLX判断可行 不使用的估计函数的可重复覆盖的搜索树将十分庞大 #include <iostream> #include <cstring> #include < ...

  3. HDU 2295 Radar (重复覆盖)

    Radar Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  4. HDU 2295 Radar (二分 + Dancing Links 重复覆盖模型 )

    以下转自 这里 : 最小支配集问题:二分枚举最小距离,判断可行性.可行性即重复覆盖模型,DLX解之. A*的启发函数: 对当前矩阵来说,选择一个未被控制的列,很明显该列最少需要1个行来控制,所以ans ...

  5. HDU 2295 Radar dancing links 重复覆盖

    就是dancing links 求最小支配集,重复覆盖 精确覆盖时:每次缓存数据的时候,既删除行又删除列(这里的删除列,只是删除表头) 重复覆盖的时候:只删除列,因为可以重复覆盖 然后重复覆盖有一个估 ...

  6. hdu 3498 whosyourdaddy 重复覆盖

    题目链接 重复覆盖的入门题, 和精确覆盖不一样, 删除的时候只删除一行多列. #include<bits/stdc++.h> using namespace std; #define pb ...

  7. dancing link 精确覆盖 重复覆盖 (DLX)

    申明:因为转载的没有给出转载链接,我就把他的链接附上,请尊重原创: http://www.cnblogs.com/-sunshine/p/3358922.html 如果谁知道原创链接 给一下,请尊重原 ...

  8. [ACM] HDU 2295 Radar (二分法+DLX 重复覆盖)

    Radar Problem Description N cities of the Java Kingdom need to be covered by radars for being in a s ...

  9. 搜索(DLX重复覆盖模板):HDU 2295 Radar

    Radar Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

随机推荐

  1. 如何打印枚举类型:%d

    #include <stdio.h> typedef enum SessionState { SESSION_OPENING, /* Session scope is being crea ...

  2. HTML 捕获window.close() 并做窗口关闭前的处理工作

    转自:http://www.xinotes.net/notes/note/261/ <html> <head> <script language="JavaSc ...

  3. H5图片上传、压缩

    1.注册input file标签的onchange事件: 2.检查图片格式: 3.检查图片大小: 4.压缩图片 5.上传图片至服务器: 前端代码: document.getElementById('i ...

  4. 【转】python 关键字

    转自:http://www.cnblogs.com/hongten/p/hongten_python_keywords.html python3.3.2中的关键字如下: The following i ...

  5. ES6重点知识点总结(2)

    ES6重点知识点总结(2) call和apply的作用是什么?区别是什么? call和apply的功能基本相同,都是实现继承或者转换对象指针的作用: 唯一不通的是前者参数是罗列出来的,后者是存到数组中 ...

  6. OO第三单元总结——JML规格设计

    • 1.JML语言的理论基础.应用工具链情况 JML(Java Modeling Language)—— java建模语言,是一种行为接口规范语言( behavioral interface spec ...

  7. MVC设计模式与JavaWEB三层架构

    一.MVC设计模式 MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controlle ...

  8. DDL表结构修改

      *1)创建表    create table 表名(     字段名 类型,     ....    );     //以现有表复制一个新表   create table j012 as   se ...

  9. 关于C++的一些函数的使用方法

    关于C++的一些函数的使用方法: http://www.shouce.ren/api/c/index.html

  10. 宿主机mac os无法连接到虚拟机centos

    宿主机: Mac OS 10.9.2 虚拟机: [root@localhost ~]# cat /etc/redhat-release CentOS release 6.4 (Final) [root ...