最小重量机器设计问题

Review: 看看是否可用分支限界法来解决此问题

问题

设某一机器由 m 个部件组成,每一种部件都可以从 n 个不同的供应商处购得。 设 weight[i][j] 是从供应商 j 处购得部件 i 的重量,cost[i][j] 是相应的价钱。 试设计一个算法,给出总价格不超过 c 的最小重量机器设计
要求计算出最小重量,和每个部件所对应的供应商

例如:

  • m = 3
    n = 3
    c = 4

  • 重量 weight[i][j]

    部件/供应商-重量

  • 价格 cost[i][j]

    部件/供应商-价格

求解得到:

  • 最小重量 = 4

  • 每个部件所对应的供应商如下图:

    部件/供应商

思路

求解满足约束(总价格不超过 c)的解,还很容易想到用回溯法来求解。 只是回溯法一般求解所有解,当然了既然能求解出所有解,计算出最优解也不是难事

将每次求得的解与上次求得的解做比较,看看哪个解的重量要小,然后舍去另一个解。 在每次测试某个节点是否满足的约束的时候,可加入限界函数, 如果这时的总重量已经大于上个解的总重量,那么即使满足约束也不必继续搜索

代码

以下代码并不是全部代码

#include <string.h>

struct data_machine {
    int init_flag;      /* 方便清理,标记初始化的时候是否用了 malloc 分配空间 */
    int solution_flag;  /* 标记是否有解 */
    int part;           /* 部件数目 */
    int supplier;       /* 供应商数目 */
    int max_cost;       /* 允许的最大费用 */
    int min_weight;     /* 已求得的最小重量和 */
    int *path;          /* 递归路径,可得到 min_weight 有哪些重量组成 */
    int *min_path;      /* 最小重量和的递归路径 */
    int **weight;       /* 部件/重量,矩阵 */
    int **cost;         /* 部件/价格,矩阵 */
};

/*
 * 满足约束返回 TRUE, 否则返回 FALSE
 */
int constraint(struct data_machine *data, int cost)
{
    if (cost > data->max_cost) {
        return FALSE;
    }
    return TRUE;
}

/*
 * 满足减枝条件返回 TRUE, 否则返回 FALSE
 */
int bound(struct data_machine *data, int weight)
{
    if (data->solution_flag == TRUE) {
        if (weight >= data->min_weight) {
            return TRUE;
        }
    }
    return FALSE;
}

/*
 * 处理求得的解
 */
void result(struct data_machine *data, int weight)
{
    if (data->solution_flag == FALSE) {
        data->solution_flag = TRUE;
        data->min_weight = weight;
        memcpy(data->min_path, data->path, sizeof(int) * data->part);
    } else {
        if (data->min_weight > weight) {
            data->min_weight = weight;
            memcpy(data->min_path, data->path, sizeof(int) * data->part);
        }
    }
}

void minimum_weight_iter(struct data_machine *data,
        int part, int weight, int cost)
{
    if (part == data->part) {
        result(data, weight);
        return;
    }

    for (int i = 0; i < data->supplier; i++) {
        data->path[part] = i;
        if (constraint(data, cost + data->cost[part][i]) == TRUE
            && bound(data, weight + data->weight[part][i]) == FALSE) {
            minimum_weight_iter(data, part + 1,
                    weight + data->weight[part][i], cost + data->cost[part][i]);
        }
    }
}

void minimum_weight(struct data_machine *data)
{
    minimum_weight_iter(data, 0, 0, 0);
}