'''
对R进行二分搜索, 二分枚举出来的R值能够确定每一个雷达能覆盖哪些城市,将每一个雷达作为一个选择,其覆盖的城市作为特征值
问题就变成了验证DLX最小重复覆盖的行数是否是小于等于K的,问题就解决了
'''
from functools import lru_cache
from typing import List
class DlxRepeatOvelap:
# max_node_num是节点池的大小,取1节点大小即可, row_num和col_num是矩阵的行数和列数
# one_points是1节点的坐标的二元组(ii, jj)的列表,行坐标和列坐标都是从1开始(注意不是从0开始)
def __init__(self, max_node_num, row_num, col_num, one_points: List):
max_node_num += col_num+1 # 加上哨兵的节点数
self.__row_num = row_num
self.__col_num = col_num
self.__pos = 0 # 当前空闲的末尾位置
# 上下左右后继的节点id
self.uu, self.dd, self.ll, self.rr = [0]*max_node_num, [0]*max_node_num, [0]*max_node_num, [0]*max_node_num
self.row, self.col = [0] * max_node_num, [0] * max_node_num # 节点的行和列
self.one_num = [0] * (self.__col_num + 1) # 列上的1计数值
self.one_points = one_points
self.__boot()
# 十字链表状态初始化
def __boot(self):
one_points = self.one_points
one_points.sort()
# 最上面一行0号节点到col_num号节点都是哨兵, 都是链表头,不是实际1节点,0号节点下面不会接其他节点,只作为是横向的哨兵
uu, dd, ll, rr = self.uu, self.dd, self.ll, self.rr
col_num, col = self.__col_num, self.col
for jj in range(col_num + 1):
ll[jj] = jj - 1
rr[jj] = jj + 1
uu[jj] = jj
dd[jj] = jj
col[jj] = jj
ll[0], rr[col_num] = col_num, 0
self.__pos = col_num + 1
# 逐行添加节点
i = 0
n = len(one_points)
row, col, one_num = self.row, self.col, self.one_num
while i < n:
j = i
h_node = None # 一行的第一个节点
while j < n and one_points[j][0] == one_points[i][0]:
ii, jj = one_points[j]
pos = self.__pos
row[pos], col[pos] = ii, jj
one_num[jj] += 1
uu[pos], dd[pos] = jj, dd[jj]
uu[dd[jj]] = pos
dd[jj] = pos
# 新节点总是放在头节点的右边
if h_node is None:
h_node = pos
ll[h_node], rr[h_node] = h_node, h_node
else:
ll[pos], rr[pos] = h_node, rr[h_node]
ll[rr[h_node]] = pos
rr[h_node] = pos
j += 1
self.__pos += 1
i = j
# c节点所在的列上除了c节点以外,其他的节点都在水平方向断开
def remove_col(self, c):
uu, dd, ll, rr = self.uu, self.dd, self.ll, self.rr
node = dd[c]
while node != c:
ll[rr[node]] = ll[node]
rr[ll[node]] = rr[node]
node = dd[node]
# c节点所在的列上除了c节点以外,其他的节点都在水平方向接回来
def resume_col(self, c):
uu, dd, ll, rr = self.uu, self.dd, self.ll, self.rr
node = uu[c]
while node != c:
ll[rr[node]] = node
rr[ll[node]] = node
node = uu[node]
# 估价函数,预估最少还需要选择多少行才能完全覆盖所有列
def score(self):
uu, dd, ll, rr = self.uu, self.dd, self.ll, self.rr
overlap = [0] * (self.__col_num + 1)
cnt = 0
node = rr[0]
while node != 0:
if overlap[node] == 1:
node = rr[node]
continue
cnt += 1
overlap[node] = 1
# 该列的所有行全部都选中
mm = dd[node]
while mm != node:
nn = rr[mm]
while nn != mm:
overlap[self.col[nn]] = 1
nn = rr[nn]
mm = dd[mm]
node = rr[node]
return cnt
# DFS找最小的可行解
def dfs(self, step, max_step, path: List):
uu, dd, ll, rr = self.uu, self.dd, self.ll, self.rr
if step + self.score() > max_step:
return False
if rr[0] == 0:
return True
# 选1最少的行
c = rr[0]
min_one_num = 0x7fffffff
min_col = None
while c != 0:
if self.one_num[c] < min_one_num:
min_one_num = self.one_num[c]
min_col = c
c = rr[c]
# 针对min_col列,枚举能够选择的行
node = dd[min_col]
while node != min_col:
nn = rr[node]
while nn != node:
self.remove_col(nn)
nn = rr[nn]
self.remove_col(node)
path.append(self.row[node])
if self.dfs(step+1, max_step, path):
return True
path.pop(-1)
self.resume_col(node)
nn = ll[node]
while nn != node:
self.resume_col(nn)
nn = ll[nn]
node = dd[node]
return False
# 迭代加深获取一个最小的可行解
def get_one_minimal_solution(self):
path = []
for bound in range(1, self.__col_num + 1):
if self.dfs(0, bound, path):
return path
return None
def sign(val):
if abs(val) < 10 ** (-8):
return 0
if val < 0:
return -1
return 1
T = int(input())
for _ in range(T):
city = []
rada = []
N, M, K = map(int, input().split())
for _ in range(N):
x, y = map(int, input().split())
city.append((x, y))
for _ in range(M):
x, y = map(int, input().split())
rada.append((x, y))
l, r = 0, 2000
ans = None
while abs(l-r) >= 10 ** (-10):
#print(l, r)
mid = (l + r) / 2
one_points = []
for row in range(1, M+1):
rx, ry = rada[row - 1]
for col in range(1, N+1):
cx, cy = city[col - 1]
if sign((cx-rx)**2 + (cy-ry)**2 - mid**2) <= 0:
one_points.append((row, col))
algo = DlxRepeatOvelap(M*N, M, N, one_points)
ret = algo.get_one_minimal_solution()
if ret is None or len(ret) > K:
l = mid
else:
r = mid
print("%.6f" % l)