选择原料工厂

来源:互联网 发布:中关村人工智能活动季 编辑:程序博客网 时间:2021/04/13 09:42

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<=nstatic 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

原创粉丝点击