最小距离最大值问题

49 篇文章 0 订阅
28 篇文章 1 订阅

#!/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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值