题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5046

题意:

给定n个城市的坐标,要在城市中建k个飞机场,使城市距离最近的飞机场的最长距离最小,求这个最小距离。

分析:

最小化最大值,显然二分最大距离。然后我们将距离在范围内的两个城市建边,看能否选出k个城市,使得覆盖了所有城市。

将点之间的关系转化成01矩阵的覆盖问题,重复覆盖,建好边套个DLX即可。

看了鸟神博客,这里可以直接将所有距离保存在一个数组中,排序并去重,二分下标即可。这样快了很多很多!

hdu 2295 和这题一个套路,更裸一些。

跳舞链好强大,可惜只会用模板,这个讲的还挺清晰

代码:

/*************************************************************************
> File Name: O.cpp
> Author: jiangyuzhu
> Mail: 834138558@qq.com
> Created Time: Fri 08 Jul 2016 03:31:58 PM CST
************************************************************************/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
#define sal(n) scanf("%I64d", &(n))
#define sa(n) scanf("%d", &(n))
typedef long long ll;
const int maxn = 3600 + 5, maxc = 60 + 5, maxr = 60 + 5, inf = 0x3f3f3f3f;
struct Node{ll x; ll y;}city[maxn];
int L[maxn], R[maxn], D[maxn], U[maxn], C[maxn];
int S[maxc], H[maxr], size;
int n, m, k;
ll d[maxr][maxc], t[maxn];
///不需要S域
void Link(int r, int c)
{
S[c]++; C[size] = c;
U[size] = U[c]; D[U[c]] = size;
D[size] = c; U[c] = size;
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;
}
int h()
{///用精确覆盖去估算剪枝
int ret = 0;
bool vis[maxc];
memset (vis, false, sizeof(vis));
for(int i = R[0]; i; i = R[i]){
if(vis[i]) continue;
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[C[k]] = true;
}
return ret;
}
int ans;
bool Dance(int a) //具体问题具体分析
{
if(a + h() > k) return 0;
if(!R[0]) return a <= k;
int c = R[0];
for (int i = R[0]; i; i = R[i])
if(S[i] < S[c]) 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(a + 1)) return 1;
for (int j = L[i]; j != i; j = L[j])
resume(j);
resume(i);
}
return 0;
}
void initL(int x)///col is 1~x,row start from 1
{
for (int i = 0; i <= x; ++i){
S[i] = 0;
D[i] = U[i] = i;
L[i+1] = i; R[i] = i+1;
}///对列表头初始化
R[x] = 0;
size = x + 1;///真正的元素从m+1开始
memset (H, -1, sizeof(H));
///mark每个位置的名字
}
ll dist(int i, int j)
{
ll d = abs(city[i].x - city[j].x) + abs(city[i].y - city[j].y);
return d;
}
bool judge(ll mid)
{
initL(n);
ans = 0x3f3f3f3f;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(d[i][j] <= mid){
Link(i, j);
}
}
}
return Dance(0);
}
int main (void)
{
int T;sa(T);
for(int tt = 1; tt <= T; tt++){
sa(n);sa(k);
ll maxd = 0;
int cnt = 0;
for(int i = 1; i <= n; i++){
scanf("%I64d%I64d", &city[i].x, &city[i].y);
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
d[i][j] = dist(i, j);
t[cnt++] = d[i][j];
}
}
sort(t, t + cnt);
int ncnt = unique(t, t + cnt) - t;
ll l = -1, r = ncnt;
while(r - l > 1){
ll mid = (l + r) / 2;
if(judge(t[mid])) r = mid;
else l = mid;
}
printf("Case #%d: %I64d\n", tt, t[r]);
}
return 0;
}

HDU 5046 Airport【DLX重复覆盖】的更多相关文章

  1. hdu 5046 Airport 二分+重复覆盖

    题目链接 给n个点, 定义两点之间距离为|x1-x2|+|y1-y2|. 然后要选出k个城市建机场, 每个机场可以覆盖一个半径的距离. 求在选出点数不大于k的情况下, 这个半径距离的最大值. 二分半径 ...

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

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

  3. HDU 5046 Airport(dlx)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5046 题意:n个城市修建m个机场,使得每个城市到最近进场的最大值最小. 思路:二分+dlx搜索判定. ...

  4. HDU 5046 Airport(DLX反复覆盖)

    HDU 5046 Airport 题目链接 题意:给定一些机场.要求选出K个机场,使得其它机场到其它机场的最大值最小 思路:二分+DLX反复覆盖去推断就可以 代码: #include <cstd ...

  5. (中等) HDU 3335 , DLX+重复覆盖。

    Description As we know,the fzu AekdyCoin is famous of math,especially in the field of number theory. ...

  6. HDU 3957 Street Fighter (最小支配集 DLX 重复覆盖+精确覆盖 )

    DLX经典题型,被虐惨了…… 建一个2*N行3*N列的矩阵,行代表选择,列代表约束.前2*N列代表每个人的哪种状态,后N列保证每个人至多选一次. 显然对手可以被战胜多次(重复覆盖),每个角色至多选择一 ...

  7. hdu 2295 dlx重复覆盖+二分答案

    题目大意: 有一堆雷达工作站,安放至多k个人在这些工作站中,找到一个最小的雷达监控半径可以使k个工作人所在的雷达工作站覆盖所有城市 二分半径的答案,每次利用dlx的重复覆盖来判断这个答案是否正确 #i ...

  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 (重复覆盖)

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

随机推荐

  1. nginx基本安全优化

    一.调整参数隐藏nginx软件版本号信息 查看nginx版本信息: [root@nginx conf]# curl -I 192.168.200.102 HTTP/1.1 200 OK Server: ...

  2. 有关Kali的方法

    Kali 找回系统登陆密码的方式:https://jingyan.baidu.com/article/47a29f24560e77c0142399e3.html

  3. Word 借助VBA一键实现插入交叉引用

    最近写论文的时候,经常需要向上或向下插入题注的交叉引用,word 自带的界面往往需要操作多次,才能实现插入.而平时使用较多的只是交叉引用附近的题注,比如如图1.1所示,在图1.1中等,距离较远的引用则 ...

  4. Java-basic-7-面向对象

    继承 在Java中,每个子类只能有一个父类,但可以继承多个接口. 子类继承父类,类定义的时候用extends. 继承接口,用implements. 重写 声明为final的方法不能被重写. 声明为st ...

  5. iOS 中的视图函数 init initwithnib viewDidLoad viewWillAppear的总结

    我要总结的函数主要是这几个: UIView *view-如果view还没有被初始化的话,getter方法会先调用[self loadView],如果getter或者setter方法被重写了,子类中的g ...

  6. Linux学习-Linux的账号与群组

    使用者识别码: UID 与 GID Linux 主机并不会直接认识 你的"帐号名称"的,他仅认识 ID 啊 (ID 就是一组号码啦). 由于计算机仅认识 0 与 1,所 以主机对于 ...

  7. hierarchy viewer不能获取userbuild手机版本的UI布局

    步骤很详细:http://maider.blog.sohu.com/255485243.html 其中的第7步命令需要更改为: java -jar smali-2.0.3.jar ./out -o c ...

  8. UVa 1630 区间DP Folding

    一个字符串如果能简写,要么是重复多次,按题中的要求简写:要么是左右两个部分分别简写后再拼起来. dp(i, j)表示字串(i, j)所能被简写的最短的字符串. 判断一个字符串是否为周期串以及求出它的周 ...

  9. 一步一步解剖Libevent源代码 - 0

    本系列文章将在<Libevent源码深度解剖>的基础上,结合Libevent-2.0.22代码,更新了其中的一些定义和说明,以及加上了bufferevent部分.   一.Libevent ...

  10. 通用的前端js代码

    1.判断是否移动设备的浏览器,是否允许触摸事件.(响应式网页) if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i. ...