求解最小机器重量设计问题,回溯思路,C++代码实现

求解最小机器重量设计问题

题目内容:

设某一机器由n个部件组成,部件编号为1~n,每一种部件都可以从m个不同的供应商处购得,供应商编号为1~m。设wij是从供应商j处购得的部件i的重量,cij是相应的价格。对于给定的机器部件重量和机器部件价格,计算总价格不超过d的最小重量机器设计。(注意:输出结果中第一行最后没有空格。比如下面的输出样例中1 3 1后面没有空格。)

输入格式:

第1行输入3个正整数n,m和d。接下来n行输入wij(每行m个整数),最后n行输入cij(每行m个整数),这里1≤n、m≤100。

输出格式:

输出的第1行包括n个整数,表示每个对应的供应商编号,第2行为对应的最小重量。

输入样例:

3 3 7

1 2 3

3 2 1

2 3 2

1 2 3

5 4 2

2 1 2

输出样例:

1 3 1

4

在本题中,题目中意为每个零件都需要进行购买,即每个零件都要选取其中的元素进入集合。

首先加入影响,进入下一层。之后在遍历完毕后消除影响,加入下一个元素。

对于每个解首先进行存储,在判断为更优解后存储至最优解中。

在输出时,直接进行判断是否为最后一位输出,若不为最后一位输出则输出空格,最后输出换行符即可满足题意。

#include<iostream>
using namespace std;

int n, m, d;
int bestw = 03f3f3f3f;  // 设置一位最大值     
int w[101][101];        // 对应的两个分别存储重量和价格的二维数组
int c[101][101];
int cw, cv;             // cw指目前的重量和,cv指目前的价格和
int x[101];             // 存储最优解
int y[101];             // 存储目前解

void BackTrack(int t)
{
    if(t > n)
    {
        if(cv <= d && cw < bestw)
        {
            bestw = cw;
            for(int i = 1; i <= n; i ++)
                x[i] = y[i];                   // 对于最优解进行修正
        }
    }
    else
    {
        for(int j = 1; j <= m; j ++)
        {
            
            if(w[t][j] + cw <= d)
            {
                y[t] = j;
                cw += w[t][j];
                cv += c[t][j];
                BackTrack(t + 1);              // 回溯
                cw -= w[t][j];
                cv -= c[t][j];
            }
        }
    }
}

int main()
{
    scanf("%d %d %d", &n, &m, &d);
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++)
            scanf("%d", &w[i][j]);

    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++)
            scanf("%d", &c[i][j]);
    
    BackTrack(1);
    for(int i = 1; i <= n; i ++)
    {
        printf("%d", x[i]);
        if(i != n)printf(" ");
    }
    puts("");
    printf("%d", bestw);
    return 0;
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
连续邮资问题是一个经典的组合优化问题,可以使用回溯算法来解决。在C++中,可以这样实现: ```cpp #include <iostream> #include <vector> using namespace std; // 回溯函数 void backtrack(vector<int>& stamps, vector<int>& combinations, int target, int current, int& minCombLen) { if (target == 0) { // 当目标值为0时,找到了一种组合方案 minCombLen = min(minCombLen, (int)combinations.size()); return; } if (target < 0 || current >= stamps.size()) { // 当目标值小于0或者已经遍历完所有邮资面额时,无法组合出目标值 return; } // 不选择当前面额 backtrack(stamps, combinations, target, current + 1, minCombLen); // 选择当前面额 if (target - stamps[current] >= 0) { combinations.push_back(stamps[current]); backtrack(stamps, combinations, target - stamps[current], current, minCombLen); combinations.pop_back(); } } int main() { vector<int> stamps = {1, 3, 4}; // 假设有1分、3分和4分的邮票 int target = 7; // 目标邮资为7分 vector<int> combinations; int minCombLen = INT_MAX; backtrack(stamps, combinations, target, 0, minCombLen); if (minCombLen == INT_MAX) { cout << "无法组合出目标邮资" << endl; } else { cout << "最少需要" << minCombLen << "张邮票" << endl; } return 0; } ``` 以上代码使用了回溯算法求解连续邮资问题。首先定义了一个回溯函数`backtrack`,其中`stamps`表示邮票的面额,`combinations`表示当前的邮票组合,`target`表示目标邮资,`current`表示当前考虑的邮票面额的索引,`minCombLen`表示当前的最小组合长度。 在回溯函数中,首先判断目标值是否为0,如果是,则找到了一种组合方案,更新最小组合长度。然后判断目标值是否小于0或者已经遍历完所有邮资面额,如果是,则无法组合出目标值,直接返回。接下来,分别尝试不选择当前面额和选择当前面额两种情况,并进行递归调用。如果选择当前面额时,需要将当前面额加入到组合中,并将目标值减去当前面额。递归调用结束后,需要将当前面额从组合中移除,以便尝试其他组合。 最后,在`main`函数中定义了初始的邮票面额和目标邮资,并调用回溯函数求解最少需要的邮票张数。如果最小组合长度为INT_MAX,则说明无法组合出目标邮资;否则,输出最少需要的邮票张数。 希望这个回溯算法实现对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值