1

我一直在研究这个问题,并且可以得到一些结果,但是在这里实现分支和绑定方法时遇到了麻烦。
你们能帮帮我吗?

建造仓库

描述

中了彩票后,您决定购买几辆卡车(或卡车)。您的目标是将货物运送到科英布拉的所有超市。但是现在你必须建立仓库来储存货物,你必须考虑可能的位置。理想情况下,仓库应靠近超市,以降低运输成本。然而,你不可能把所有的钱都花在到处建仓库上,所以你必须做出一个聪明的决定:考虑到在每个可能的地点建造每个仓库的固定成本以及未来 5 年从每个地点为每个超市提供服务的运输成本,您想知道应该在哪里建造仓库,以便在该期间内的总成本(运输和固定成本)最小。注意至少要建一个仓库。此外,总运输成本的计算必须考虑到必须为所有超市提供服务。

输入

每个测试用例都包含有关在给定地点建造仓库的固定成本以及与每个地点和超市相关的运输成本的信息。每个测试用例的第一行给出了可以建造仓库的可能位置的数量(n<51)和超市的数量(m<16)。然后,以下 n 行中的每一行给出了在该位置建造仓库的成本以及与从该位置供应 m 个超市中的每一个相关的运输成本。

输出

输出是建造和运营仓库的最低总成本(整数)。例子

输入:

4 5

10 8 6 10 8 10

9 1 2 10 4 8

10 6 4 2 1 5

1 10 4 6 9 3

输出:

26

http://pastebin.com/apXCMdxy

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

struct set {
    int *nodes;
    int position;
    int size;
    int capacity;
};

int locations;
int supermarkets;





void calc_custo(int **matrix, struct set *set, int *lower){


    int i;
    int last;
    int cost;
    int t;
    int j;
    int *mins;
    struct set *new_set;
    new_set = malloc(sizeof(struct set));
    new_set->nodes = malloc(new_set->capacity * sizeof(int));

    mins = malloc((supermarkets + 1) * sizeof(int));
    /*
    for (i = 0; i < set->size; i ++) {
        printf("%d ", set->nodes[i]);
    }
    printf("\n");*/
    for(j = 0; j < supermarkets + 1; j++) {
        mins[j] = INT_MAX;
    }   

    cost = 0;
    for(i = 0; i < set->size; i ++) {
        t = set->nodes[i];
        cost += matrix[t][0];
         for(j = 1; j < supermarkets + 1; j++) {
             if (mins[j] > matrix[t][j]) {
                 mins[j] = matrix[t][j];
             }

         }
    }

    for(j = 1; j < supermarkets + 1; j++) {
        cost += mins[j];
    }

    free(mins);

    memcpy(new_set, set, sizeof(struct set));
    memcpy(new_set->nodes, set->nodes, set->capacity * sizeof(int));

    if (cost < *lower) {
        *lower = cost;

    }

    if (set->position < set->capacity) {
        set->nodes[set->size] = set->position;
        set->size++;
        set->position++;
        calc_custo(matrix, set, lower);

    }

    if (new_set->position < new_set->capacity) {
        new_set->nodes[new_set->size - 1] = new_set->position;
        new_set->position++;
        calc_custo(matrix, new_set, lower);
    }

}


int main (int argc, const char* argv[])
{


    int t;
    int i, j;
    int lower;
    int **matrix;

    /*allocat matrix*/

    scanf("%d", &locations);
    scanf("%d", &supermarkets);

    matrix = malloc(locations * sizeof(int*));
    for (i = 0; i < locations; i++){
        matrix[i] = malloc((supermarkets + 1) * sizeof(int));

    }

    struct set *set;
    set = malloc(sizeof(struct set));
    set->nodes = malloc(locations * sizeof(int));
    set->size = 1;
    set->position = 1;
    set->capacity = locations;
    set->nodes[0] = 0;

    for (i = 0; i < locations; i++) {
        for (j = 0; j < supermarkets + 1; j++) {
            scanf("%d", &t);
            matrix[i][j] = t;
        }
    }
    lower = INT_MAX;
    calc_custo(matrix, set, &lower);
    printf("%d\n", lower);
    return 0;
}
4

2 回答 2

1

Rafe 的回答是正确的——“普通”的 B&B 在这里行不通,因为分数可能会上升或下降。但问题中仍有一些结构可以利用。

任何非空的仓库集都会产生(可能不是最优的)解决方案。给定解决方案的总成本是建造所有仓库的成本加上服务所有超市的成本。给定一组仓库,显然每个超市都应该由该超市的最低成本仓库提供服务。请注意,当您将仓库添加到解决方案时,为给定仓库提供服务的成本要么保持不变,要么降低。

需要注意的一件事是,如果这样做会增加总成本,那么在解决方案中添加仓库是不值得的。为什么?

  1. 如果这是添加到解决方案中的最后一个仓库,那么显然它会增加总成本,因此不应添加。
  2. 否则,假设这是解决方案中添加的 k > i 个仓库中的第 i 个。考虑我们通过将它添加到最后一个位置而不是第 i 个位置来获得的解决方案——然后可以添加这个仓库可能降低整体成本?不,因为对于每个超市 s,在步骤 i+1 .. k 中添加的每个仓库要么降低了服务 s 的成本,要么保持不变。增加一个仓库可以产生净收益的唯一方法是能够比目前的解决方案更便宜地为一个或多个超市提供服务。如果在添加前 i-1 个步骤后不是这种情况,那么在完整解决方案中添加所有 k-1 个其他仓库后肯定不会是这种情况。这意味着稍后添加仓库的净成本始终与较早添加仓库相同或更差。

这可能会修剪搜索树,以使普通递归相当快地完成。

于 2011-03-13T13:02:09.193 回答
1

我不清楚标准的分支定界是否可以在这里工作。

BnB 的工作方式是强制搜索在达到部分解决方案 s 时回溯,只要将 s 扩展到完整解决方案的成本不能提高迄今为止找到的最佳完整解决方案的成本。这取决于能够说明任何部分解决方案成本的下限,s。

在这个问题中,对部分解决方案 s 的一步扩展既可以提高总体成本,也可以降低总体成本(如果它使运送到超市的成本低于建造额外仓库的成本),这使得下界陈述相当困难以有用的方式陈述。

于 2011-03-13T05:53:02.547 回答