HDU 2295 Radar 重复覆盖 DLX
题意:
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的更多相关文章
- hdu 2295 Radar 重复覆盖+二分
题目链接 给m个雷达, n个城市, 以及每个城市的坐标, m个雷达里只能使用k个, 在k个雷达包围所有城市的前提下, 求最小半径. 先求出每个雷达到所有城市的距离, 然后二分半径, 如果距离小于二分的 ...
- HDU 2295.Radar (DLX重复覆盖)
2分答案+DLX判断可行 不使用的估计函数的可重复覆盖的搜索树将十分庞大 #include <iostream> #include <cstring> #include < ...
- HDU 2295 Radar (重复覆盖)
Radar Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- HDU 2295 Radar (二分 + Dancing Links 重复覆盖模型 )
以下转自 这里 : 最小支配集问题:二分枚举最小距离,判断可行性.可行性即重复覆盖模型,DLX解之. A*的启发函数: 对当前矩阵来说,选择一个未被控制的列,很明显该列最少需要1个行来控制,所以ans ...
- HDU 2295 Radar dancing links 重复覆盖
就是dancing links 求最小支配集,重复覆盖 精确覆盖时:每次缓存数据的时候,既删除行又删除列(这里的删除列,只是删除表头) 重复覆盖的时候:只删除列,因为可以重复覆盖 然后重复覆盖有一个估 ...
- hdu 3498 whosyourdaddy 重复覆盖
题目链接 重复覆盖的入门题, 和精确覆盖不一样, 删除的时候只删除一行多列. #include<bits/stdc++.h> using namespace std; #define pb ...
- dancing link 精确覆盖 重复覆盖 (DLX)
申明:因为转载的没有给出转载链接,我就把他的链接附上,请尊重原创: http://www.cnblogs.com/-sunshine/p/3358922.html 如果谁知道原创链接 给一下,请尊重原 ...
- [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 ...
- 搜索(DLX重复覆盖模板):HDU 2295 Radar
Radar Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
随机推荐
- ESM定义模块部分export用法
//定义一个函数和变量 fonction myFunc(){}; const My_CONST=''; export {My_CONST AS THE_COMST,myFunc as THE_FUNC ...
- luoguP1002
p1002 题意: 从坐标A到坐标B的可能路线(有一些点不能走)情况,很明显可以看出用dp做 m[i][j]=m[i-1][j]+m[i][j-1](注意处理不能走的点) 自己在初始化时犯了错,第1行 ...
- EasyUI——DataGrid的自定义单元格点击事件
1.当点击的单元格需要传递参数,并且传递的是row的值时,需要进行转义 function initCompareTable(){ $("#deviceCompareTable"). ...
- .net基础总复习(1)
第一天 1.new关键字 (1) 创建对象 (2) 隐藏从父类那里继承过来的成员 2.访问修饰符 public: 公开的,公共的. private:私有的,只能在当前类的内部访问,类中的成员, 如果不 ...
- Vue文件封装日历组件
封装就是要具有灵活性,样式自适应,调用的时候传入props就可以变成自己想要的样式. 效果展示网址:https://1963331542.github.io/ 源代码: <template> ...
- HDU 3068 最长回文( Manacher模板题 )
链接:传送门 思路:Manacher模板题,寻找串中的最长回文子串 /***************************************************************** ...
- CF1037E Trips (离线+图上构造)
题目大意:一共有n个人,每天早上会有两个人成为朋友,朋友关系不具有传递性,晚上,它们会组织旅游,如果一个人去旅游,那么他不少于$k$个朋友也要和他去旅游,求每天的最大旅游人数 一开始并没有想到反向建图 ...
- cron 和anacron 、日志转储的周期任务
一.cron是开机自动启动的 [root@localhost ~]# chkconfig --list | grep "cron" crond 0:off 1:off 2:on 3 ...
- PHP下的异步尝试一:初识生成器
PHP下的异步尝试系列 PHP下的异步尝试一:初识生成器 PHP下的异步尝试二:初识协程 PHP下的异步尝试三:协程的PHP版thunkify自动执行器 PHP下的异步尝试四:PHP版的Promise ...
- oracle 用户解锁和修改用户密码
1.安装教程参看:https://jingyan.baidu.com/article/3c48dd34be2a32e10be35881.html 2.用户解锁 --> 运行cmd --> ...