下面的代码99%参考了这个网站http://www.cnblogs.com/183zyz/archive/2011/08/07/2130193.html

人生的第一道DLX肯定是需要作一些参考的啦。

题意:给你N个城市,M个雷达,你要在其中选K个,问当半径最小是多少的时候可以覆盖到所有的N个城市。

做法:二分所需要的半径r,然后处理出这时雷达能够覆盖到哪些位置。然后就转化成了一个重复覆盖问题,跑一下DLX即可。

花了两天的时间学习了一下DLX这种神奇的数据结构,它在解决精确覆盖问题上尤其有帮助,因为随着每次选的一行,对应的包含了这个行的列的行也不会再用到,所以整个图会很快的变得非常小,从而可以极大得加快搜索速度。但是重复覆盖就没有缩小得那么快,包含了对应的列的行是不会消除掉的。

下面对模板的一些数组说下理解  L,R,U,D就是链表的四个方向,其中H是行的头指针,当该行不存在东西的时候H[]=-1,而col[size]表示结点编号为size所在的是哪一列,在精确覆盖的时候还要多维护一个row[size]去表示是在哪一行。对应的link函数是用来加条件的,然后dance就是递归,remove和resume则是对应的删除和恢复,在重复覆盖和精确覆盖问题上这两个操作要做相应的修改。

题目了用了个A*,多亏我有数据结构大作业的基础,A*就是在搜的时候多了个估价函数,但是这个估价函数必须保证不能高估了可能的解,譬如解是6的话你不能估成7,这样的估价函数是不行的。下面给的h函数是一定估小的,虽然我觉得可能优化的不是特别的大。

细节等别的地方后面再慢慢学习,先照着别人的拍一题加深一下认识。。

#pragma warning(disable:4996)
#include<iostream>
#include<cstring>
#include<string>
#include<vector>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std; #define maxnode 4000
#define maxn 80
#define eps 1e-8
int L[maxnode], R[maxnode], U[maxnode], D[maxnode];
int col[maxnode];
int S[maxn], H[maxn];
int size;
int n, m, K; int ak; // currently best dep void link(int r, int c)
{
S[c]++; col[size] = c;
U[size] = U[c]; D[U[c]] = size;
D[size] = c; U[c] = size; if (H[r] == -1) H[r] = L[size] = R[size] = size;
else{
L[size] = L[H[r]]; R[L[H[r]]] = size;
R[size] = H[r]; L[H[r]] = size;
}
size++;
} 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]] = R[L[i]] = i;
}
}
// evaluating function
int hfunc()
{
bool vis[maxn];
memset(vis, 0, sizeof(vis));
int cnt = 0;
for (int i = R[0]; i; i = R[i]){
if (vis[i]) continue;
cnt++; vis[i] = true;
for (int j = D[i]; j != i; j = D[j]){
for (int k = R[j]; k != j; k = R[k]){
vis[col[k]] = true;
}
}
}
return cnt;
} void dance(int dep)
{
int ans = hfunc();
if (ans + dep > K || ans + dep >= ak) return;
if (R[0] == 0){
if (dep < ak) ak = dep; return;
}
int minv = maxn; int c;
for (int i = R[0]; i; i = R[i]){
if (S[i] < minv) minv = 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);
}
dance(dep + 1);
for (int j = L[i]; j != i; j = L[j]){
resume(j);
}
resume(i);
}
return;
} double x[100], y[100];
double xx[100], yy[100]; int dcmp(double x){
return (x > eps) - (x < -eps);
} double dist(double x1, double y1, double x2, double y2){
return sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
} int main()
{
int T; cin >> T;
while (T--)
{
scanf("%d%d%d", &n, &m, &K);
for (int i = 1; i <= n; i++){
scanf("%lf%lf", &x[i], &y[i]);
}
for (int i = 1; i <= m; i++){
scanf("%lf%lf", &xx[i], &yy[i]);
}
double l = 0, r = 1500;
while (dcmp(r - l) > 0){
for (int i = 0; i <= n; i++){
S[i] = 0; U[i] = D[i] = i;
L[i + 1] = i; R[i] = i + 1;
}
R[n] = 0;
memset(H, -1, sizeof(H)); size = n + 1; double mid = (l + r) / 2;
for (int i = 1; i <= m; i++){
for (int j = 1; j <= n; j++){
if (mid>=dist(xx[i], yy[i], x[j], y[j])){
link(i, j);
}
}
}
ak = maxn;
dance(0);
if (ak <= K) r = mid;
else l = mid;
}
printf("%.6lf\n", l);
}
return 0;
}

HDU2295 Radar (DLX)的更多相关文章

  1. HDU2295 Radar —— Dancing Links 可重复覆盖

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2295 Radar Time Limit: 2000/1000 MS (Java/Others)     ...

  2. HDU 2295 Radar (DLX + 二分)

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

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

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

  4. 【转】DLX 精确覆盖 重复覆盖

    问题描述: 给定一个n*m的矩阵,有些位置为1,有些位置为0.如果G[i][j]==1则说明i行可以覆盖j列. Problem: 1)选定最少的行,使得每列有且仅有一个1. 2)选定最少的行,使得每列 ...

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

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

  6. Dancing Links 专题总结

    算法详细:Dancing Links博客 1.精确覆盖: ZOJ3209 Treasure Map HUST1017 Exact cover POJ3074 Sudoku 2.可重复覆盖: HDU22 ...

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

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

  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. HDU 2295 Radar 重复覆盖 DLX

    题意: N个城市,M个雷达站,K个操作员,问雷达的半径至少为多大,才能覆盖所有城市.M个雷达中最多只能有K个同时工作. 思路: 二分雷达的半径,看每个雷达可以覆盖哪些城市,然后做重复覆盖,判断这个半径 ...

随机推荐

  1. WPF中线性渐变画刷的一个小窍门

    最近被项目里面控件的设计搞的死去活来的,大部分的设计都会需要使用进度条的功能,因为UI形状的变态,使用ProgressBar不能满足需求,没办法就自己想办法实现进度显示.折腾的多了发现一个很不错的方法 ...

  2. Python 文件I/O

    文件I/O是Python中最重要的技术之一,在Python中对文件进行I/O操作是非常简单的. 1.打开文件 语法: open(name[, mode[, buffering]]) 1.1文件模式 1 ...

  3. linux kernel 0.11 setup

    setup作用 ①读取参数放在0x90000处. ②将原本在0x10000处的system模块移至0x00000处 ③加载中断描述符表,全局描述符表,进入32位保护模式. 概念 关于实模式和保护模式区 ...

  4. 删除undotbs后,数据库无法启动

    SQL> archive log list;Database log mode              No Archive ModeAutomatic archival            ...

  5. Objective-C-实例变量与属性的关系

    当在一个类创建一个属性,Xcode编译器就会自动产生一个带下划线的同名实例变量: 一般来说,如果getter这个属性采用下划线的方式获取效率更高,而setter采用self.属性名更加合理. 读取实例 ...

  6. NSKeyValueObserving(KVO)

    NSKeyValueObserving非正式协议定义了一种机制,它允许对象去监听其它对象的某个属性的修改. 我们可以监听一个对象的属性,包括简单属性,一对一的关系,和一对多的关系.一对多关系的监听者会 ...

  7. LC_ALL=C

    设置LC_ALL=C,可以让sort按照字节排序;

  8. C++异常机制知识点

     在这里总结一下,C++中的异常机制,以及如何使用异常的知识点 C++中处理异常的过程是这样的:在执行程序发生异常,可以不在本函数中处理,而是抛出一个错误信息,把它传递给上一级的函数来解决,上一级解决 ...

  9. iOS 取得单张系统图片

    这里主要用到了UIImagePickerController 不多废话,直接上代码 // // RootViewController.m // GetImageFromPhotoAlbum // // ...

  10. MATLAB中匿名函数与符号函数的转换

    符号函数举例: syms x y=x+1; y1=diff(y); %求导 匿名函数举例: z=@(x)(x(1)+2*x(2)); t=z([2 3]); %计算z在x=[2 3]处的值 z=@(x ...