现在的位置: 首页 > 综合 > 正文

选择原料工厂

2018年02月19日 ⁄ 综合 ⁄ 共 2489字 ⁄ 字号 评论关闭

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个原料厂的最短距离,B[i][j]表示从第i个工厂到第j个工厂选择1个原料厂的最短距离。

对B[i][j]而言,1<=i<=j<=N

对A[i][j]而言,1<=j<=i<=N

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

i, j, k满足的条件为:1<=j-1<=k<i, k+1<=i

即,2<=j<=i, j-1<=k<=i

为什么j-1要大于等于1呢?若j-1等于0, 则前k个工厂没有原料厂了。

所以,递归解为:

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

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


源程序:

// 12个工厂分布在一条东西向高速公路的两侧,工厂距离公路最西端的距离分别是0、4、5、10、12、18、27、30、 31、38、39、47.
// 在这12个工厂中选取3个原料供应厂,使得剩余工厂到最近的原料供应厂距离之和最短,问应该选哪三个厂?
// 参数:
// array: 工厂距离数组,array[1...n]为有效值,array[0]置0
// length: 有效元素数目
// 求从第begin个工厂到第end个工厂设1个原料厂的最短距离
// 1<=begin<=end<=n
static int min_distance(int *array, int begin, int end)
{
    int mid = begin + (end - begin) / 2;
    int distance = 0;
    for (int i = begin; i <= end; ++i)
    {
        distance += abs(array[i]-array[mid]);
    }
    return distance;
}
// 输出从前i个工厂选择的j个原料厂
static void print_selected_factory(const multi_array<int, 2> &opt, int length, int i, int j)
{
    if (i <= j)
    {
        for (int k = 1; k <= i; ++k)
        {
            cout << k << " ";
        }
        return;
    }

    int k = opt[i][j];
    print_selected_factory(opt, length, k, j-1);
    cout << k+1 + (i-k-1)/2 << " ";
}
int min_sum_of_distance(int *array, int length, int number)
{
    if (array == NULL || length < 1)
        return 0;

    // min_distance_1[i][j]表示从第i个工厂到第j个工厂设1个原料厂的最短距离
    multi_array<int, 2> min_distance_1(extents[length+1][length+1]);
    for (int i = 0; i <= length; ++i)
        min_distance_1[i][0] = 0;
    for (int j = 1; j <= length; ++j)
        min_distance_1[0][j] = 0;
    for (int i = 1; i <= length; ++i)
        for (int j = i; j <= length; ++j)
            min_distance_1[i][j] = min_distance(array, i, j);

    // min_distance_m[i][j]表示从前i个工厂中设j个原料厂的最短距离之和
    multi_array<int, 2> min_distance_m(extents[length+1][length+1]);
    multi_array<int, 2> opt(extents[length+1][length+1]);
    for (int i = 0; i <= length; ++i)
        min_distance_m[i][0] = 0;
    for (int j = 1; j <= length; ++j)
        min_distance_m[0][j] = 0;
    for (int i = 1; i <= length; ++i)
    {
        int j = 1;
        min_distance_m[i][j] = min_distance_1[1][i];
        for (j = 2; j <= i; ++j)
        {
            min_distance_m[i][j] = INT_MAX;
            for (int k = max(1, j-1); k < i; ++k)
            {
                int tmp = min_distance_m[k][j-1] + min_distance_1[k+1][i];
                if (tmp < min_distance_m[i][j])
                {
                    min_distance_m[i][j] = tmp;
                    opt[i][j] = k;
                }
            }
        }
    }
            
    cout << "min distance: " << min_distance_m[length][number] << endl;
    print_selected_factory(opt, length, length, number);
    cout << endl;
    return min_distance_m[length][number];
}

int main(int argc, char **argv)
{
    int array[] = {0, 0, 4, 5, 10, 12, 18, 27, 30, 31, 38, 39, 47};
    int length = sizeof(array) / sizeof(int);
    min_sum_of_distance(array, length-1, 3);
    return 0;
}

参考:

http://blog.csdn.net/julianxiong/article/details/7381214

抱歉!评论已关闭.