hdu 2295 Radar(重复覆盖问题)
2016-03-11 19:45
260 查看
Radar
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2295解题思路:
题目大意:有m个雷达,每个雷达的覆盖范围都为以r为半径的圆,给定他们的坐标,有n个城市,给定他们的坐标,求最小的r,使得每个城市
都被雷达覆盖,限制条件为最多只有k个雷达工作。
算法思想:
二分答案, 然后使用重复覆盖的Dancing Links模板进行判断,看使用k个能不能覆盖n个点。
首先建图:m行,n列的矩形,也就是横坐标代表雷达,纵坐标代表城市,如果雷达与城市之间的距离小于等于当前的r,则坐标处标记
为1,否则为0,这样就转化为了01矩阵,也就是解决问题能不能在这个矩阵中找出一些行(行数小于等于k),使得这些行组成的新
矩阵,每列都至少有一个1(重复覆盖,每列可以有多个1).
这里有一个A*的优化:估价函数h意义为从当前状态最好情况下需要添加几条边才能覆盖。
AC代码:
#include <iostream> #include <cstdio> #include <cmath> using namespace std; const int maxnode = 3000; const int maxm = 55; const int maxn = 55; int k; struct DLX{ int n,m,len; int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode]; int H[maxn];//行头结点 int S[maxm];//每列有多少个结点 int ansd,ans[maxn];//如果有答案,则选了ansd行,具体是哪几行放在ans[]数组里面,ans[0~ansd-1] void init(int _n,int _m){ n = _n;m = _m; for(int i = 0; i <= m; i++){ S[i] = 0; U[i] = D[i] = i;//初始状态时,上下都指向自己 L[i] = i-1; R[i] = i+1; } R[m] = 0,L[0] = m; len = m;//编号,每列都有一个头结点,编号1~m for(int i = 1; i <= n; i++) H[i] = -1;//每一行的头结点 } void link(int r,int c){//第r行,第c列 ++S[Col[++len]=c];//第len个节点所在的列为c,当前列的结点数++ Row[len] = r;//第len个结点行位置为r D[len] = D[c]; U[D[c]] = len; U[len] = c; D[c] = len; if(H[r] < 0) H[r] = L[len] = R[len] = len; else{ R[len] = R[H[r]]; L[R[H[r]]] = len; L[len] = H[r]; R[H[r]] = len; } } void del(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; } bool v[maxnode]; int f(){ int ret = 0; for(int c = R[0]; c != 0; c = R[c]) v[c] = true; for(int c = R[0]; c != 0; c = R[c]){ if(v[c]){ ret++; v[c] = false; for(int i = D[c]; i != c; i = D[i]){ for(int j = R[i]; j != i; j = R[j]){ v[Col[j]] = false; } } } } return ret; } bool dance(int d){//递归深度 if(d + f() > k) return false; if(R[0] == 0) return d <= k; int c = R[0]; for(int i = R[0]; i != 0; i = R[i]){ if(S[i] < S[c]) c = i; } for(int i = D[c]; i != c; i = D[i]){ del(i); ans[d] = Row[i];//列头节点下面的一个节点 for(int j = R[i]; j != i; j = R[j]) del(j); if(dance(d+1)) return true; for(int j = L[i]; j != i; j = L[j]) resume(j); resume(i); } return false; } }; DLX head; const double eps = 1e-8; struct point{ double x,y; }city[maxn],station[maxn]; double dis(point a,point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int main(){ int T; scanf("%d",&T); while(T--){ int n,m; scanf("%d%d%d",&n,&m,&k); for(int i = 0; i < n; i++) scanf("%lf%lf",&city[i].x,&city[i].y); for(int i = 0; i < m; i++) scanf("%lf%lf",&station[i].x,&station[i].y); double l = 0, r = 3000; while(r - l >= eps){ double mid = (l+r)/2; head.init(m,n); for(int i = 0; i < m; i++){ for(int j = 0; j < n; j++){ if(dis(station[i],city[j]) < mid - eps) head.link(i+1,j+1); } } if(head.dance(0)) r = mid - eps; else l = mid + eps; } printf("%.6lf\n",l); } return 0; }
相关文章推荐
- HUST 1017 Exact cover
- HUST 1017 Exact cover(Dancing Links)(精确覆盖问题)
- ZOJ 3209 Treasure Map(Dancing Links)(精确覆盖问题)
- FZU 1686 神龙的难题(重复覆盖|Dancing Links)
- 一切不以Eng 抑或 官网 reference 为参考的 例子都是扯淡
- External Links Module 友情链接模块
- useful open source links
- x
- 跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题
- 通用链接universal links中遇到的问题
- hust1017Exact cover(Dancing Links)
- iPhone开发 – iPhonAn App ID with Identifier 'XX.XX' is not available. Please enter a different string
- 创建通用链接
- Universal links(页面跳转app)
- Linux中硬链接和软连接的介绍
- about recommender system
- 手动安装m4, autoconf, automake, libtool
- iOS 需要注意的地方
- 会议纪要二:自主去优化你的代码,优化你的逻辑
- 寻找百度图片搜索接口历程--one