这段代码只是使用暴力法解决了01背包问题,但是没有经过优化,效率不高。
使用暴力法的原因只是因为作业需求,请勿评价。
主要的难点在于使用C语言列出一个数组的所有子集。使用了递归的方法,将每次的计算都归并为二个元素,这样就能够简化问题。
//
// main.c
// BackPack
//
// Created by shadowdai on 11-10-25.
// Copyright 2011年 __MyCompanyName__. All rights reserved.
//
#include <stdio.h>
//k是开始字符的位置,n是数组的长度,l是子集的位数
void subArray(int W[], int V[], int k,int l, int n);
//初始化整个子集数组
void initArray(int n);
//用于输出子集的数组
int priArray[4];
void printArray(int W[], int n);
//计算子集的个数
int counter;
int subArrayWeight[16];
int subArrayValue[16];
//计算子集的重量和价值
void sumOfWeightAndValue(int W[], int V[], int m, int n);
//寻找重量不超过背包重量,并且价值最大的子集
int searchMax();
//重量和价值数组
int main()
{
int i;
int max;
int array[4] = {7, 3 , 4, 5};
int value[4] = {42, 12, 40, 25};
//0是所有数组的子集
printf("The No.1 is: 0\n");
subArrayWeight[0] = 0;
subArrayValue[0] = 0;
counter = 1;
for (i = 0; i < 4; i++)
{
initArray(4);
//递归算法需要保证从第一个元素开始的所有的元素都被遍历到
priArray[0] = i;
counter ++;
sumOfWeightAndValue(array, value, counter, 1);
printArray(array, 1);
subArray(array, value, i+1, 2, 4);
}
printf("\nThere are %d SubArray.\n", counter);
for (i = 0; i < 16; i++)
{
printf("The Weight of %d is %d and the value is %d\n", i+1 , subArrayWeight[i], subArrayValue[i]);
}
max = searchMax();
printf("\nThe most valuable package is No.%d, the max value is %d.\n", max+1, subArrayValue[max]);
return 0;
}
/*
* 该递归算法每次只向后寻找一位数字。
* 例如k=1时,只会寻找2,3,4;k=2时,只会寻找3,4
*/
void subArray(int W[], int V[], int k, int l, int n)
{
int i;
if (k == n-1)
{
//n是整个数组的长度,k是整个子集的上一位字符,当k == n-1时,意味着已经是最后一个了。
priArray[l-1] = k;
counter += 1;
sumOfWeightAndValue(W, V, counter, l);
printArray(W, l);
}
else
{
for ( i= k; i <= n-1; ++i)
{
priArray[l-1] = i;
counter += 1;
sumOfWeightAndValue(W, V, counter, l);
printArray(W, l);
subArray(W, V, i+1, l+1,n);
}
}
}
/*
* 打印子集数组的函数
*/
void printArray(int W[], int n)
{
int i;
printf("The No.%d is: " , counter);
for (i = 0; i < n; i++)
{
printf("%d ", W[priArray[i]]);
}
printf("\n");
}
/*
* 初始化子集数组
*/
void initArray(int n)
{
for (int i = 0; i<= n-1 ; i++) {
priArray[i] = 0;
}
}
/*
* 计算子集的重量和价值综合
* m是该子集的序号,与counter相同。n是数组长度
*/
void sumOfWeightAndValue(int W[], int V[], int m, int n)
{
int i;
int sumWeight = 0, sumValue = 0;//重量和价值总和变量
for ( i = 0; i < n; i++) {
sumWeight += W[priArray[i]];
sumValue += V[priArray[i]];
}
subArrayWeight[m-1] = sumWeight;
subArrayValue[m-1] = sumValue;
}
/*
* 排序并查找所有子集中最大子集
*/
int searchMax()
{
int i,max,MAX;
max = 0;
MAX = subArrayValue[max];
for (i = 0; i < 16; i++) {
if (subArrayWeight[i] <= 10)
{
if (subArrayValue[i] >= MAX)
{
max = i;
MAX = subArrayValue[max];
}
}
}
return max;
}
分享到:
相关推荐
01背包问题是一种经典的组合优化问题,常在计算机科学,特别是算法设计与分析领域中被研究。它模拟了这样一个场景:我们有一组物品,每件物品都有一定的重量和价值,我们需要将这些物品装入一个容量有限的背包中,以...
文档详细阐述了使用动态规划法求解背包问题的步骤。动态规划是一种常用的解决背包问题的方法,其核心思想是将大问题划分为较小的子问题,并利用子问题的解来构建最终解。具体来说,我们可以定义二维数组`dp(i,j)`表示在...
### 01背包问题与动态规划法解析 在计算机科学领域,背包问题是一类经典的组合优化问题,其中01背包问题是最基础也是最典型的一种。01背包问题的基本设定是:给定一组物品,每种物品都有自己的重量和价值,在限定的...
01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2……Wn,与之相对应的价值为P1,P2……Pn。
分支定界法是一种求解背包问题的有效算法。它通过构建一棵搜索树,将问题分解为多个子问题,然后采用剪枝策略消除无望成为最优解的分支。这种方法可以确保找到全局最优解,但计算量较大,适用于规模较小的问题。 ...
然而,随着问题规模的增加,穷举法的计算复杂度呈指数增长,因此在实际应用中往往需要考虑其他更为高效的求解方法。对于初学者而言,掌握穷举法的基础原理和实现是理解更高级优化技术的重要基石。
01背包问题是一种经典的组合优化问题,常在计算机科学、运筹学以及人工智能等领域出现。它的目标是在容量有限的背包中选择物品,使得装入背包的物品总价值最大,但每个物品都有自己的重量和价值,并且背包只能容纳...
【背包问题】是一种经典的计算机科学优化问题,常用于求解有限资源的最大利用。它通过模拟放入背包中的物品,以达到最大价值或满足特定条件。在动态规划领域,背包问题是一个非常重要的模型,因为它能直观地展示动态...
在0/1背包问题中,回溯法会递归地尝试包含或不包含当前物品的两种情况,直到找到最优解。虽然这种方法直观易懂,但效率通常低于动态规划。 3. 剪枝策略(Pruning): 在回溯法的基础上,可以加入剪枝策略来提高...
0-1背包问题是一种经典的组合优化问题,在计算机科学和运筹学中有着广泛的应用。它模拟了许多实际场景,如资源分配、项目选择、装载问题等。在这个问题中,我们有一组物品,每件物品都有一个重量和一个价值,以及一...
0-1背包问题的多种解法,包括暴力求解、动态规划求解、回溯法、贪心法求解求解、模拟退火算法,C++源代码,有详细的注释
除了动态规划之外,文档还提到了背包问题的搜索解法,这通常指的是回溯法等暴力搜索的解决方案,是背包问题的另一种解法,但在面对大规模数据时效率往往不高。 在文档的前言部分,作者强调了动态规划学习中思考的...
虽然看起来仍然较高,但对比于暴力求解的O(2^n)已经有了显著提升。 此外,还有一些优化技巧可以提高算法效率,例如剪枝操作,通过提前判断某些状态不可能得到最优解而减少不必要的计算。还有记忆化搜索,利用已计算...
通过动态规划求解0-1背包问题,时间复杂度是O(nW),其中n是物品数量,W是背包容量。这种方法避免了暴力枚举所有可能的组合,大大提高了效率。在实际应用中,动态规划可以解决各种类似的优化问题,如旅行商问题、最长...
这类习题有助于培养总结经验、状态转移的思维能力,如背包问题、最长公共子序列等。 4. 贪心算法习题 贪心算法通过局部最优选择来近似获得全局最优解,在某些场景下可以极高效地解决问题。这类习题有助于启发我们从...
分枝限界法适用于求解组合优化问题,如背包问题、旅行商问题等。特别是在解空间较大但存在有效的限界函数时,分枝限界法能够高效地找到最优解。 #### 优点与局限性 - **优点**:相比于单纯的穷举法,分枝限界法能够...
蛮力法,又称暴力求解,是通过穷举所有可能的解决方案来寻找最优解。虽然这种方法在小规模问题中可行,但随着问题规模的增长,其效率会急剧下降。例如,在解决旅行商问题(TSP)时,若城市数量增加,计算量将以指数...
动态规划是一种优化技术,主要用来解决复杂的问题,通过将大问题分解为小的、相互关联的子...理解和掌握动态规划是成为优秀程序员的关键技能之一,因为它能够解决许多复杂问题,而且通常比朴素的暴力求解方法更有效。
通过阅读和理解这段代码,我们可以深入理解分支界限法如何应用于0-1背包问题,学习如何设计高效的数据结构和算法来求解此类问题。 分支界限法相比简单的暴力枚举,其优势在于可以显著减少搜索空间,提高求解效率。...