其他分享
首页 > 其他分享> > 某公司运筹优化岗位第一次面试

某公司运筹优化岗位第一次面试

作者:互联网

P问题, NP问题, NPC问题, NP-hard问题

  1. 基本概念
  1. P问题, NP问题, NPC问题, NP-hard问题的定义和相互关系

参考资料:

动态规划解背包问题

一维背包问题

def dynamicAlgorithm_Knapscak(w, v, b):
    """用动态规划方法求解背包问题
    输入:
        w: 物品的重量 dtype int
        v: 物品的价值 dtype int
        b: 背包的重量
    输出:
        x:最优解,各个物品是否装入背包
        max_value:装入背包的物品的重量
    """
    # 判断异常
    if len(w)!=len(v):
        print('请检查输入')
        return -1,0
    
    # 边界条件
    n = len(w)
    # F[i,j] 当背包重量为j,可取前i个物品时,可装入物品的最大重量
    F = np.zeros((n+1, b+1), dtype=int) 
    # info[i,j],当背包重量为j,可取前i个物品时, 装入的物品的最大标号
    info = np.zeros((n+1, b+1), dtype=int)  
    F[:,0] = 0
    F[0,:] = 0
    
    # 递推 转移方程:F_k(y) = F_k(y-x) + v_k
    for y in range(1,b+1):
        for k in range(1,n+1):
            F[k, y] = F[k-1, y]
            info[k, y] = info[k-1, y]
            if (y-w[k-1] >= 0) & ( F[k-1, y-w[k-1]]+v[k-1] > F[k, y]):
                F[k, y] = F[k-1,y-w[k-1]] + v[k-1]
                info[k, y] = k
                
    # 追踪结果
    x = np.zeros(n, dtype=int)
    max_value = F[-1,-1]
    k = info[-1,-1]
    leftb = b
    while k > 0:
        x[k-1] = 1
        leftb = leftb - w[k-1]
        k = info[k-1, leftb]
    # 输出
    return x, max_value
v = np.random.randint(1,100,1000,dtype=int)
w = np.random.randint(1,100,1000,dtype=int)
b = int(w.sum()*0.4)
x, max_value = dynamicAlgorithm_Knapscak(w, v, b)
print(x.sum(), max_value)

解二维背包问题

def dynamicAlgorithm_Knapscak(w, v, b):
    """
    w: 物品的重量和体积 多维数组,dtype int
    v: 物品的价值 dtype int
    b: 最大体积和最大重量
    F_k(y) = F_k(y-x) + v_k
    """
    if len(w[0])!=len(v):
        print('请检查输入')
        return -1,0
    
    # 边界条件
    n = len(v)
    F = np.zeros((n+1, b[0]+1, b[1]+1), dtype=int)
    info = np.zeros((n+1, b[0]+1, b[1]+1), dtype=int) # 装入的物品的最大标号
    
    # 递推
    for k in range(1,n+1):
        for y1 in range(1,b[0]+1):
            if (y1-w[0,k-1] >= 0):
                for y2 in range(1,b[1]+1):
                    F[k, y1, y2] = F[k-1, y1, y2]
                    info[k, y1, y2] = info[k-1, y1, y2]
                    if (y2-w[1,k-1] >= 0):
                        if F[k-1, y1-w[0,k-1], y2-w[1,k-1]] + v[k-1] > F[k, y1, y2]:
                            F[k, y1, y2] = F[k-1, y1-w[0,k-1], y2-w[1,k-1]]+v[k-1]
                            info[k, y1, y2] = k
            else:
                F[k, y1, :] = F[k-1, y1, :]
                info[k, y1, :] = info[k-1, y1, :]
            
    # 追踪结果
    x = np.zeros(n, dtype=int)
    max_value = F[-1, -1, -1]
    k = info[-1, -1, -1]
    leftw = b[0]
    leftc = b[1]
    while k > 0:
        x[k-1] = 1
        leftw = leftw - w[0, k-1]
        leftc = leftc - w[1, k-1]
        k = info[k-1, leftw, leftc]
    # 输出
    return x, max_value
w = np.random.randint(1,60,(2,1000),dtype=int)
b = [120,120]
v = np.random.randint(2,5000,1000,dtype=int)
x, max_value = dynamicAlgorithm_Knapscak(w, v, b)
print('x = :',x, '\n max_value=', max_value)

参考资料:

求一个向量中的第k小的元素

def partition(nums,l,r):
        k = random.randint(l+1,r)
        nums[l], nums[k] = nums[k], nums[l]
        i = l+1    # [l+1, i) <= nums[l]
        j = r    # (j, r] > nums[l]
        while True:
            while (i <= r) and (nums[i] < nums[l]):
                i +=1
            while (j >= l+1) and nums[j] > nums[l]:
                j -=1
            if i > j:
                break
            nums[i], nums[j] = nums[j], nums[i]
            i +=1
            j -=1
        nums[l],nums[j] = nums[j], nums[l]
        return j

def findKthMinest(nums, kth):
    l = 0; r = len(nums)-1
    while True:
        mid = partition(nums, l, r)
        if mid+1 == kth:
            return nums[mid]
        elif mid+1 < kth:
            l = mid+1
            kth = kth-(mid+1)
        else:
            r = mid   

参考资料:

整数规划的求解方法总结

精确解法中遗漏了分支定价算法,入门列生成法和分支定价算法可以阅读罗纳德《运筹学》(肖永波译)第二版第13章
参考资料:

标签:info,y1,nums,int,岗位,运筹,问题,面试,NP
来源: https://www.cnblogs.com/liuxiang2020/p/11370768.html