• [经典面试题][腾讯]选择原料工厂(最短距离问题)


    题目

    12个工厂分布在一条东西向高速公路的两侧,工厂距离公路最西端的距离分别是0、4、5、10、12、18、27、30、31、38、39、47。在这12个工厂中选取3个原料供应厂,使得剩余工厂到最近的原料供应厂距离之和最短,问应该选哪三个厂 ?

    来源

    腾讯 盛大

    思路

    (1)这是一维问题,不是二维,可以抽象成:有12个点分布在一维坐标轴上,选择3个点,使得剩余的点到最近的点的距离之和最小。

    (2)工厂距离是从小到大排序的。

    (3)从n个工厂中选择1个原料厂,选择位于中位数位置的工厂,距离之和最短。

    (4)设A[i][j]表示从前i个工厂选择j个原料厂的最短距离。(1<=i<=j<=N) 
    B[i][j]表示从第i个工厂到第j个工厂选择1个原料厂的最短距离。(1<=j<=i<=N)

    从前i个工厂选择j个原料厂,可分为两部分:从前k个工厂选择j-1个原料厂和从第k+1个工厂到第i个工厂选择1个原料厂(1<=j-1<=k< i, k+1<=i)

    这里写图片描述

    所以,递归解为:

    A[i][j] = B[1][i], 即j=1时

    A[i][j] = min{ A[k][j-1] + B[k+1][i] },其中1<=j-1<=k< i, k+1<=i

    代码

    #include <iostream>
        #include <algorithm>
        #include <climits>
        #include <vector>
        #include <math.h>
        using namespace std;
    
        int fac[100][100];
    
        // n工厂个数 count原料厂个数 result原料厂下标集合
        vector<int> BestFactoryPoint(int n,int count){
            vector<int> result;
            //[1,n]
            int k;
            for(int i = 1;i <= n;){
                //[1,n]分成两部分[1,k]有count-1个原料厂[k+1,n]有1个原料厂
                k = fac[n][count--];
                // [k+1,n]有一个原料厂,中位点就是原料厂点
                result.push_back(k+1 + (n-k-1)/2);
                // 所有原料厂寻找完毕
                if(count == 0){
                    break;
                }//if
                // 如果工厂个数小于原料厂个数
                // 所有工厂全是原料厂
                if(k <= count){
                    for(int i = 1;i <= k;++i){
                        result.push_back(i);
                    }//for
                    break;
                }//if
                // 求[1,k]部分
                n = k;
            }//for
            return result;
        }
    
        // 从[start,end]选择一点使其到其他点的距离最小
        int MinDistanceOneFactory(int point[],int start,int end){
            if(start > end){
                return -1;
            }//if
            int mid = (start + end) / 2;
            // 计算距离
            int distance = 0;
            for(int i = start;i <= end;++i){
                distance += abs(point[i] - point[mid]);
            }//for
            return distance;
        }
        //
        int MinDistance(int point[],int n,int count){
            if(n <= 0){
                return -1;
            }//if
            //
            // B[i][j]表示从第i个工厂到第j个工厂设1个原料厂的最短距离
            // i <= j B上三角有用
            int B[n+1][n+1];
            // 计算第i个工厂到第j个工厂设1个原料厂的最短距离
            for(int i = 1;i <= n;++i){
                for(int j = i;j <= n;++j){
                    B[i][j] = MinDistanceOneFactory(point,i,j);
                }//for
            }//for
            // A[i][j]表示从前i个工厂中设j个原料厂的最短距离之和
            int A[n+1][n+1];
            // i前i个工厂
            for(int i = 1;i <= n;++i){
                // 设j个原料厂
                // j = 1时
                A[i][1] = B[1][i];
                for(int j = 2;j <= i;++j){
                    A[i][j] = INT_MAX;
                    for(int k = j-1;k < i;++k){
                        int curMin = A[k][j-1] + B[k+1][i];
                        if(curMin < A[i][j]){
                            A[i][j] = curMin;
                            fac[i][j] = k;
                        }//if
                    }//for
                }//for
            }//for
            return A[n][count];
        }
    
        int main() {
            int array[] = {0, 0, 4, 5, 10, 12, 18, 27, 30, 31, 38, 39, 47};
            int n = 12;
            int count = 3;
            cout<<"最小距离->"<<MinDistance(array,n,count)<<endl;
            vector<int> result = BestFactoryPoint(n,count);
            for(int i = result.size()-1;i >= 0;--i){
                cout<<array[result[i]]<<" ";
            }//for
            cout<<endl;
            return 0;
        }



    Stay Hungry, Stay Foolish, Walking in Life
  • 相关阅读:
    CentOS 7中firewall防火墙详解和配置以及切换为iptables防火墙
    使用kubeadm安装Kubernetes v1.10
    Docker版本变化和新版安装
    Kubernetes实践--hello world 示例
    kubernetes常用命令
    区块链入门教程
    Json概述以及python对json的相关操作
    linux activiti5.22 流程图乱码
    Spring Cloud Gateway 实现Token校验
    oauth table
  • 原文地址:https://www.cnblogs.com/ywx-vashon/p/4895802.html
Copyright © 2020-2023  润新知