#!/usr/bin/python3
# 文件名: 最小距离最大值问题
# 作者:巧若拙
# 时间:2019-01-23
'''
最小距离最大值问题。
描述:元组a是一个递增正整数序列(其中a[0]=0),
求从a[1:]中删除m个元素以后,剩下的元素中最小距离的最大值。
距离是指当前元素减去前一个元素的差。
函数名:distance(a, m)
参数表:a,存储了递增正整数序列的元组
m,删除的元素个数
返回值:返回剩下的元素中最小距离的最大值
例如:当a = (0,2,11,14,17,21,25),m = 2时,返回4。
分析过程:如果删除元素“2”和“11”,剩下的元素为(0,14,17,21,25),
最小距离为3,即17-14;如果删除元素“2”和“14”,剩下的元素为(0,11,17,21,25),
最小距离为4,即21-17 或者 25-21。
依次分析删除2个数的所有可能情况,可知最小距离的最大值为4。
'''
def check(a, m, x):
k, c = 0, 0
for i in range(1, len(a)):
if a[i]-a[k] >= x:#当前距离不小于x,更新左边界
c += 1
k = i
return c >= len(a) - 1 - m
def check2(a, m, x):
k, c = 0, 0
for i in range(1, len(a)):
if a[i]-a[k] < x:#当前距离小于x,删除元素a[i]
c += 1
else: #当前距离不小于x,更新左边界
k = i
return c <= m
def distance(a, m):
left, right, ans = 1, a[-1], 0
while left <= right:
mid = (left + right) // 2
if check(a, m, mid):
ans = mid
left = mid + 1
else:
right= mid - 1
return ans
def distance2(a, m):
left, right, ans = 1, a[-1], 0
while left <= right:
mid = (left + right) // 2
if check2(a, m, mid):
ans = mid
left = mid + 1
else:
right= mid - 1
return ans
def distance3(a, m):
for ans in range(a[-1], 0, -1):
if check(a, m, ans):
return ans
def distance4(a, m):
for ans in range(a[-1], 0, -1):
if check2(a, m, ans):
return ans
def min_dis(a):#返回最小距离
left = 1 #定位第一个元素,值为0的元素表示已经被删除
while a[left] == 0:
left += 1
d = a[left] #初始化最短距离为第一条线段的长度
right = left + 1
while right < len(a):
if a[right] == 0:#定位线段的右边界
right += 1
else:
if a[right] - a[left] < d: #更新最小距离
d = a[right] - a[left]
left = right #处理下一条线段
right = left + 1
return d
#效率很低的回溯算法
def distance5(a, m):
def dfs(b, top):
nonlocal dis
if top == m:
dis = max(min_dis(b), dis)
else:
for i in range(len(b)):
if b[i] > 0:
t = b[i]
b[i] = 0 #删除b[i]
dfs(b, top + 1)
b[i] = t #还原b[i]
b = list(a)
dis = 0
dfs(b, 0)
return dis
import random
import time
a = [0] * 100
for i in range(1, 100):
a[i] = a[i-1] + random.randint(10,20)
print(a)
t0 = time.process_time()
for i in range(85):
print(distance(a, i),end=" ")
t1 = time.process_time()
print()
print(t1 - t0)
t0 = time.process_time()
for i in range(85):
print(distance2(a, i),end=" ")
t1 = time.process_time()
print()
print(t1 - t0)
t0 = time.process_time()
for i in range(85):
print(distance3(a, i),end=" ")
t1 = time.process_time()
print()
print(t1 - t0)
t0 = time.process_time()
t0 = time.process_time()
for i in range(85):
print(distance4(a, i),end=" ")
t1 = time.process_time()
print()
print(t1 - t0)