回溯法介绍
回溯法实际上是一个类似穷举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”,尝试别的路径。
它适合于解一些组合数较大的最优化问题。
是一种以深度优先搜索方式在问题的解空间中系统地搜索问题的解并结合剪枝函数(Pruning)的算法。
求解回溯法问题的步骤有:
- 设计解向量:复杂问题的解是由多个小解决决策组成的序列,因此一个问题的解可以表示为满足某个条件的解向量X={x1,x2,x3…,xn}
- 设计剪枝函数:剪枝函数包括了用约束函数在扩展节点处剪去不满足约束条件的子树以及用限界函数减去得不到问题解或最优解的子树。
- 构建解空间树:解空间树中的每一个结点代表了求解过程中的一个状态,树中的边表示了xi的一个可能值,解向量就是由根结点到任意(或叶)结点的路径定义,解空间就是由根结点到所有(或叶)结点的路径定义。
题目内容
设某一机器由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
解题思路
- 对数据的存放仍然采用一元数组形式,通过layer和count两个参数分别通过行和列的计算公式layer*m+count得出数组下标,从w[]和c[]中找到对应的重量和价格
- 利用getMin()函数构建解空间树,layer表示当前的层数,第i层表示第i件商品(从0开始),count表示当前的商户数,第j个表示从第j个供应商处购买。
- 对于每一层,进行由0~m-1的遍历,在当前层选中了该商户后,进入下一层开始新的m次遍历
- 设计剪枝函数,首先是tc[layer0*m+count0]<=d这是题目要求的条件,其次是tw[layer0*m+count0]<minw,此时没有必要进行对下一层的遍历。这里使用<而不是≤,因为题目要求得到的是符合条件的第一个解。
解题代码
#include<stdio.h>
int n=