1 背包问题动态规划详解及C代码

合集下载

01背包问题回溯法c语言

01背包问题回溯法c语言

01背包问题回溯法c语言01背包问题是一个经典的动态规划问题,可以使用回溯法来解决。

在C语言中,我们可以通过递归的方式来实现回溯法解决01背包问题。

首先,让我们来看一下01背包问题的描述:给定n个物品,每个物品有一个重量和一个价值。

现在有一个背包,它能够容纳一定的重量,问如何选择装入背包的物品,使得背包中物品的总价值最大。

接下来,让我们来看一下如何使用回溯法来解决这个问题。

我们可以定义一个递归函数来尝试将每个物品放入背包或者不放入背包,然后找出最优解。

以下是一个简单的C语言代码示例:c.#include <stdio.h>。

#define N 5 // 物品的数量。

#define W 10 // 背包的容量。

int weight[N] = {2, 2, 6, 5, 4}; // 每个物品的重量。

int value[N] = {6, 3, 5, 4, 6}; // 每个物品的价值。

int maxValue = 0; // 最大的总价值。

void backtrack(int index, int currentWeight, int totalValue) {。

if (index == N || currentWeight == W) {。

if (totalValue > maxValue) {。

maxValue = totalValue;}。

return;}。

// 不放入背包。

backtrack(index + 1, currentWeight, totalValue); // 放入背包。

if (currentWeight + weight[index] <= W) {。

backtrack(index + 1, currentWeight +weight[index], totalValue + value[index]);}。

}。

int main() {。

backtrack(0, 0, 0);printf("背包能够容纳的最大总价值为,%d\n", maxValue);return 0;}。

0-1背包问题与完全背包问题C++实现动态规划

0-1背包问题与完全背包问题C++实现动态规划

0-1背包问题与完全背包问题C++实现动态规划今天看了看背包九讲,⾃⼰写了下0-1背包和完全背包王晓东《计算机算法分析与设计》上⾯给出的C++实现⽐较繁琐,相⽐⽽⾔这个版本更加简明给出了测试数据0-1背包问题C++实现的最⼤价值Sample Input 3 34 57 9Sample Output 120 1 0 1*/#include<stdio.h>#include<string.h>int c[20][1000];//c[k][y]为只允许装前k 种物品,背包总重量不超过y 的最⼤价值int inumber[21][1000];//inumber[k][u]为只允许装前K 种物品,背包总重量不超过y 时得到最⼤价值时使⽤的背包的最⼤标号int w[21],p[21];int knapsack(int m,int n){ int i,j; for(i=1;i<n+1;i++) scanf("%d%d",&w[i],&p[i]); memset(c,0,sizeof(c)); memset(inumber,0,sizeo f(inumber)); for(j=1;j<m+1;j++){ c[1][j]=j/w[1]*p[1]; } for(i=1;i<n+1;i++){ for(j=1;j<m+1;j++){ if(j >= w[i]){ if(p[i]+c[i-1][j-w[i]]>=c[i-1][j]){ c[i][j]=p[i]+c[i-1][j-w[i]]; inumber[i][j]=i; } else{ c[i][j]=c[i-1][j]; inumber[i][j]=inumber[i-1][j]; } } else{ c[i][j]=c[i-1][j]; inumber[i][j]=inumber[i-1][j]; } }题的最⼤价值Sample Input10 42 13 34 51 9Sample Output900 0 0 10*/#include<stdio.h>#include<string.h>int c[20][1000];//c[k][y]为只允许装前k 种物品,背包总重量不超过y 的最⼤价值int inumber[21][1000];//inumber[k][u]为只允许装前K 种物品,h 背包总重量不超过y 时得到最⼤价值时使⽤的背包的最⼤标号int w[21],p[21];int knapsack(int m,int n){int i,j;for(i=1;i<n+1;i++)scanf("%d%d",&w[i],&p[i]);memset(c,0,sizeof(c));memset(inumber,0,sizeof(inumber));for(j=1;j<m+1;j++){c[1][j]=j/w[1]*p[1];}for(i=1;i<n+1;i++){for(j=1;j<m+1;j++){if(j >= w[i]){if(p[i]+c[i][j-w[i]]>=c[i-1][j]){//和0-1背包相⽐只是将c[i-1][j-w[i]]写成了c[i][j-w[i]],因为完全背包问题中每件物品有⽆限个c[i][j]=p[i]+c[i][j-w[i]];inumber[i][j]=i;}else{c[i][j]=c[i-1][j];inumber[i][j]=inumber[i-1][j];}。

动态规划之01背包问题(最易理解的讲解)

动态规划之01背包问题(最易理解的讲解)

01背包问题,是用来介绍动态规划算法最经典的例子,网上关于01背包问题的讲解也很多,我写这篇文章力争做到用最简单的方式,最少的公式把01背包问题讲解透彻。

01背包的状态转换方程f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] }f[i,j]表示在前i件物品中选择若干件放在承重为j 的背包中,可以取得的最大价值。

Pi表示第i件物品的价值。

决策:为了背包中物品总价值最大化,第i件物品应该放入背包中吗?题目描述:有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最首先要明确这张表是从右到左,至底向上生成的。

为了叙述方便,用e10单元格表示e行10列的单元格,这个单元格的意义是用来表示只有物品e时,有个承重为10的背包,那么这个背包的最大价值是6,因为e物品的重量是4,背包装的了,把e装进去后价值为6。

然后是e9单元格表示背包承重9,只有物品e, e装进去后,背包价值为6,接着是e8, e7单元格,一直到e3单元格表示背包承重3,但物品e承重4,装不了,所以e3=0,对于d10单元格,表示只有物品e,d时,承重为10的背包,所能装入的最大价值,是10,因为物品e,d这个背包都能装进去。

对于承重为9的背包,d9=10,是怎么得出的呢?根据01背包的状态转换方程,需要考察两个值,一个是f[i-1,j],对于这个例子来说就是e9的值6,另一个是f[i-1,j-Wi]+Pi;在这里,f[i-1,j]表示我有一个承重为9的背包,当只有物品e可选时,这个背包能装入的最大价值f[i-1,j-Wi]表示我有一个承重为4的背包(等于当前背包承重减去物品d的重量),当只有物品e可选时,这个背包能装入的最大价值f[i-1,j-Wi]就是指单元格e4值为6,Pi指的是d物品的价值,即4由于f[i-1,j-Wi]+Pi = 6 + 4 = 10 大于f[i-1,j] = 6,所以物品d应该放入承重为9的背包,所以d9=10.。

动态规划——01背包问题

动态规划——01背包问题

动态规划——01背包问题⼀、最基础的动态规划之⼀01背包问题是动态规划中最基础的问题之⼀,它的解法完美地体现了动态规划的思想和性质。

01背包问题最常见的问题形式是:给定n件物品的体积和价值,将他们尽可能地放⼊⼀个体积固定的背包,最⼤的价值可以是多少。

我们可以⽤费⽤c和价值v来描述⼀件物品,再设允许的最⼤花费为w。

只要n稍⼤,我们就不可能通过搜索来遍查所有组合的可能。

运⽤动态规划的思想,我们把原来的问题拆分为⼦问题,⼦问题再进⼀步拆分直⾄不可再分(初始值),随后从初始值开始,尽可能地求取每⼀个⼦问题的最优解,最终就能求得原问题的解。

由于不同的问题可能有相同的⼦问题,⼦问题存在⼤量重叠,我们需要额外的空间来存储已经求得的⼦问题的最优解。

这样,可以⼤幅度地降低时间复杂度。

有了这样的思想,我们来看01背包问题可以怎样拆分成⼦问题:要求解的问题是:在n件物品中最⼤花费为w能得到的最⼤价值。

显然,对于0 <= i <= n,0 <= j <= w,在前i件物品中最⼤花费为j能得到的最⼤价值。

可以使⽤数组dp[n + 1][w + 1]来存储所有的⼦问题,dp[i][j]就代表从前i件物品中选出总花费不超过j时的最⼤价值。

可知dp[0][j]值⼀定为零。

那么,该怎么递推求取所有⼦问题的解呢。

显⽽易见,要考虑在前i件物品中拿取,⾸先要考虑前i - 1件物品中拿取的最优情况。

当我们从第i - 1件物品递推到第i件时,我们就要考虑这件物品是拿,还是不拿,怎样收益最⼤。

①:⾸先,如果j < c[i],那第i件物品是⽆论如何拿不了的,dp[i][j] = dp[i - 1][j];②:如果可以拿,那就要考虑拿了之后收益是否更⼤。

拿这件物品需要花费c[i],除去这c[i]的⼦问题应该是dp[i - 1][j - c[i]],这时,就要⽐较dp[i - 1][j]和dp[i - 1][j - c[i]] + v[i],得出最优⽅案。

动态规划------背包问题(c语言)

动态规划------背包问题(c语言)

动态规划------背包问题(c语⾔)/*背包问题:背包所能容纳重量为10;共五件商品,商品重量⽤数组m存储m[5]={2,2,6,5,4},每件商品的价值⽤数组n存储,n[5]={6,3,5,4,6};求背包所能装物品的最⼤价值。

*/#include<stdio.h>#include<conio.h>int main() {int m[5] = { 2,2,6,5,4 }, n[5] = { 6,3,5,4,6 };int flag[5] = { 0,0,0,0,0 };//符号标志位,表⽰地某个点是否装⼊背包,装⼊为1,未装⼊为0;int i, j, k;int c = 10, sum1 = 0, sum2 = 0;//sum1表⽰最终背包容纳的重量。

sum2表⽰最终背包中容纳的最⼤价值的价值。

//设⼀个⼆维数组,横坐标表⽰所装物品的标号,纵坐标表⽰背包所容纳的最⼤重量0~10;int mn[5][11];for (i = 4; i >= 0; i--) {//⼆维数组从下⾄上for (j = 0; j <= 10; j++) {if (i == 4) {if (m[i]>j)mn[i][j] = 0;elsemn[i][j] = n[i];}else {if (m[i]>j) {mn[i][j] = mn[i + 1][j];}else {mn[i][j] = mn[i + 1][j]>mn[i + 1][j - m[i]] + n[i] ? mn[i + 1][j] : mn[i + 1][j - m[i]] + n[i];}}}}for (i = 0; i<5; i++) {if (mn[i][c] != mn[i + 1][c]) {//从⼆维数组上⽅开始,背包最⼤值c,mn[i][c]的值若与mn[i+1][c]的值不同,则m[i]未放⼊背包中(之前是⾃下往上放的) flag[i] = 1;c = c - m[i];//若放⼊背包,则背包可容纳总重量减少;}printf("%d ", flag[i]);}//输出所放⼊的物品序号for (i = 0; i<5; i++) {if (flag[i] == 1) {sum1 += m[i];sum2 += n[i];}}printf("\n背包容纳的重量为:%d 背包容纳的总价值为:%d", sum1, sum2);getch();return0;}。

01背包问题c语言代码回溯法

01背包问题c语言代码回溯法

以下是使用C语言实现01背包问题的回溯法代码:```c#include <stdio.h>#include <stdlib.h>// 初始化背包struct knapsack {int maxWeight; // 背包最大承重int *items; // 物品数组int n; // 物品数量};// 定义物品重量、价值和数量int weights[] = {2, 2, 6, 5, 4};int values[] = {6, 3, 5, 4, 6};int quantities[] = {3, 2, 2, 1, 1};// 初始化背包最大承重和当前承重int maxWeight = 10;int currentWeight = 0;// 初始化最大价值为0int maxValue = 0;// 遍历物品数组void traverseItems(struct knapsack *knapsack, int index) { // 对于每个物品,遍历其数量for (int i = 0; i < knapsack->quantities[index]; i++) {// 如果当前物品可以放入背包装且当前承重不超过背包最大承重,计算放入该物品后的总价值,并更新最大价值if (currentWeight + weights[index] <= knapsack->maxWeight) {int currentValue = values[index] * knapsack->quantities[index];if (currentValue > maxValue) {maxValue = currentValue;}}// 回溯,将当前物品从背包装中移除,递归地尝试下一个物品knapsack->quantities[index]--;if (index < knapsack->n - 1) {traverseItems(knapsack, index + 1);}knapsack->quantities[index]++; // 恢复物品数量,以便下次遍历尝试放入其他物品}}// 主函数int main() {// 初始化背包装和物品数组struct knapsack knapsack = {maxWeight, weights, 5};knapsack.items = (int *)malloc(sizeof(int) * knapsack.n);for (int i = 0; i < knapsack.n; i++) {knapsack.items[i] = values[i] * quantities[i]; // 根据价值和数量计算物品价值,并存储在物品数组中}knapsack.n = quantities[4]; // 由于最后一个物品的数量为1,因此只需遍历前n-1个物品即可得到所有可能的结果// 使用回溯法求解01背包问题,返回最大价值traverseItems(&knapsack, 0);printf("The maximum value is %d.\n", maxValue);free(knapsack.items); // 释放内存空间return 0;}```希望以上信息能帮助到你。

0-1背包问题c++版

0-1背包问题c++版

0/1背包问题动态规划详解及C++代码1. 问题描述给定一个载重量为C的背包,有n个物品,其重量为w i,价值为v i,1<=i<=n,要求:把物品装入背包,并使包内物品价值最大2. 问题分析在0/1背包问题中,物体或者被装入背包,或者不被装入背包,只有两种选择。

循环变量i,j意义:前i个物品能够装入载重量为j的背包中数组c意义:c[i][j]表示前i个物品能装入载重量为j的背包中物品的最大价值若w[i]>j,第i个物品不装入背包否则,若w[i]<=j且第i个物品装入背包后的价值>c[i-1][j],则记录当前最大价值(替换为第i个物品装入背包后的价值)其c++代码如下#include<iostream>using namespace std;void KANPSACK_DP(int c[50][50], int w[50], int v[50], int n, int C){for(int i = 0; i <= C; i ++){c[0][i] = 0;}for(int i = 1; i <= n; i ++){c[i][0] = 0;for(int j = 1; j <= C; j ++){if(w[i] <= j){if(v[i] + c[i - 1][j - w[i]] > c[i - 1][j])c[i][j] = v[i] + c[i - 1][j - w[i]];else c[i][j] = c[i - 1][j];}else c[i][j] = c[i - 1][j];}}}void OUTPUT_SACK(int c[50][50], int x[50], int w[50], int n, int C) {for(int k = n; k >= 2; k --){if(c[k][C] == c[k-1][C])x[k] = 0;else {x[k] = 1;C = C - w[k];}}x[1] = c[1][C] ? 1 : 0;}int main(){int c[50][50];int w[50],v[50];int x[50];int C,n;cout<<"输入物品的总个数:";cin>>n;cout<<"输入背包的总容量:";cin>>C;cout<<"依次输入物品的重量:"<<endl;for(int i = 1; i <= n; i ++){cin >> w[i];}cout<<"依次输入物品的价值:"<<endl;for(int i = 1; i <= n; i ++){cin >> v[i];}KANPSACK_DP(c, w, v, n, C);OUTPUT_SACK(c, x, w, n, C);cout<<"最优解为:"<<endl;for(int i = 1; i <= n; i ++){cout<<x[i]<<" ";}cout<<endl<<"最大容量为:"<<endl;cout<<c[n][C]<<endl;system("pause");return 0;}运行结果如下输入物品的总个数:5输入背包的总容量:10依次输入物品的重量:2 2 6 5 4依次输入物品的价值:6 3 5 4 6最优解为:1 1 0 0 1最大容量为:15请按任意键继续. . .。

动态规划方案解决算法背包问题实验报告含源代码

动态规划方案解决算法背包问题实验报告含源代码

动态规划方案解决算法背包问题实验报告含嘿,大家好!今天我来给大家分享一个相当有趣的编程问题——背包问题。

这可是算法领域里的经典难题,也是体现动态规划思想的好例子。

我会用我10年的方案写作经验,给大家带来一份详细的实验报告,附带哦!让我简单介绍一下背包问题。

假设你是一个盗贼,要盗取一个博物馆里的宝贝。

博物馆里有n个宝贝,每个宝贝都有它的价值v和重量w。

你有一个承重为W的背包,你希望放入背包的宝贝总价值最大,但总重量不能超过背包的承重。

这个问题,就是我们要解决的背包问题。

一、算法思路1.创建一个二维数组dp,dp[i][j]表示前i个宝贝放入一个承重为j的背包中,能达到的最大价值。

2.初始化dp数组,dp[0][j]=0,因为如果没有宝贝,那么无论背包承重多少,价值都是0。

3.遍历每个宝贝,对于每个宝贝,我们有两种选择:放入背包或者不放入背包。

4.如果不放入背包,那么dp[i][j]=dp[i-1][j],即前i-1个宝贝放入一个承重为j的背包中,能达到的最大价值。

5.如果放入背包,那么dp[i][j]=dp[i-1][j-w[i]]+v[i],即前i-1个宝贝放入一个承重为j-w[i]的背包中,加上当前宝贝的价值。

6.dp[i][j]取两种情况的最大值。

二、defknapsack(W,weights,values,n):dp=[[0for_inrange(W+1)]for_inrange(n+1)]foriinrange(1,n+1):forjinrange(1,W+1):ifj>=weights[i-1]:dp[i][j]=max(dp[i-1][j],dp[i-1][j-weights[i-1]]+values[i -1])else:dp[i][j]=dp[i-1][j]returndp[n][W]测试数据W=10weights=[2,3,4,5]values=[3,4,5,6]n=len(values)输出结果max_value=knapsack(W,weights,values,n)print("最大价值为:",max_value)三、实验结果分析通过上面的代码,我们可以得到最大价值为15。

C语言动态规划之背包问题详解

C语言动态规划之背包问题详解

C语⾔动态规划之背包问题详解01背包问题给定n种物品,和⼀个容量为C的背包,物品i的重量是w[i],其价值为v[i]。

问如何选择装⼊背包的物品,使得装⼊背包中的总价值最⼤?(⾯对每个武平,只能有选择拿取或者不拿两种选择,不能选择装⼊某物品的⼀部分,也不能装⼊物品多次)声明⼀个数组f[n][c]的⼆维数组,f[i][j]表⽰在⾯对第i件物品,且背包容量为j时所能获得的最⼤价值。

根据题⽬要求进⾏打表查找相关的边界和规律根据打表列写相关的状态转移⽅程⽤程序实现状态转移⽅程真题演练:⼀个旅⾏者有⼀个最多能装M公⽄的背包,现在有n件物品,它们的重量分别是W1、W2、W3、W4、…、Wn。

它们的价值分别是C1、C3、C2、…、Cn,求旅⾏者能获得最⼤价值。

输⼊描述:第⼀⾏:两个整数,M(背包容量,M<= 200)和N(物品数量,N<=30);第2…N+1⾏:每⾏两个整数Wi,Ci,表⽰每个物品的质量与价值。

输出描述:仅⼀⾏,⼀个数,表⽰最⼤总价值样例:输⼊:10 42 13 34 57 9输出:12解题步骤定义⼀个数组dp[i][j]表⽰容量为j时,拿第i个物品时所能获取的最⼤价值。

按照题⽬要求进⾏打表,列出对应的dp表。

W[i](质量)V[i](价值)01234567891000000000000210011111111133001334444444500135568899790013556991012对于⼀个动态规划问题设置下标时最好从0开始,因为动态规划经常会和上⼀个状态有关系!从上⾯的dp表可以看出来对于⼀个物品我们拿还是不难需要进⾏两步来判断。

第⼀步:判断背包当前的容量j是否⼤于物品当前的质量,如果物品的质量⼤于背包的容量那么就舍弃。

第⼆步:如果背包可以装下这个物品,就需要判断装下该物品获取的最⼤价值是不是⼤于不装下这个物品所获取的最⼤价值,如果⼤于那么就把东西装下!根据这样的思想我们可以得到状态转移⽅程:如果单签背包的容量可以装下物品:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);如果当前背包的容量装不下该物品:dp[i][j]=dp[i-1][j];#include <stdio.h>int max(const int a,const int b){return a>b ? a:b;}int main(){int w[35]={0},v[35]={0},dp[35][210]={0};int n,m;scanf("%d %d",&m,&n);int i,j;for(i=1;i<=n;i++){scanf("%d %d",&w[i],&v[i]);}for(i=1;i<=n;i++){for(j=1;j<=m;j++){if(j>=w[i])//如果当前背包的容量⼤于商品的质量{dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);//判断是否应该拿下}else//⼤于背包的当前容量{dp[i][j]=dp[i-1][j];}}}for(int k=0;k<=n;k++){for(int l=0;l<=m;l++){printf("%d ",dp[k][l]);}printf("\n");}printf("%d\n",dp[n][m]);}通过运⾏以上程序可以看到最终的输出dp表和我们的预期是相符合的!但是并没有结束,动态规划有⼀个后⽆效性原则(当前状态只与前⼀个状态有关)。

背包问题C语言程序设计

背包问题C语言程序设计

1 问题要求及任务描述1.1 题目要求假设有一个能装入总体积为T的背包和n件体积分别为w1 , w2 , … , wn 的物品,能否从n件物品中挑选若干件恰好装满背包,即使w1 +w2 + … + wn=T,要求找出所有满足上述条件的解。

例如:当T=10,各件物品的体积{1,8,4,3,5,2}时,可找到下列4组解:(1,4,3,2)(1,4,5)(8,2)(3,5,2)。

1.2 主要任务在给定物品数量,物品各自体积和背包体积的前提下,找出物体组合后的总体积与背包体积相等的物体组合2 解决问题的主要思路和方法2.1 关键问题如何选择第i件物品:(1)考虑物品i被选择,这种可能性仅当包含它不会超过方案总重量限制时才是可行的。

选中后,继续去考虑其余物品的选择。

(2)考虑物品i不被选择,这种可能性仅当不包含物品i也有可能会找到价值更大的方案的情况。

2.2 拟采用解决问题的方法可利用回溯法的设计思想来解决背包问题。

首先将物品排成一列,然后顺序选取物品装入背包,假设已选取了前i 件物品之后背包还没有装满,则继续选取第i+1件物品,若该件物品"太大"不能装入,则弃之而继续选取下一件,直至背包装满为止。

但如果在剩余的物品中找不到合适的物品以填满背包,则说明"刚刚"装入背包的那件物品"不合适",应将它取出"弃之一边",继续再从"它之后"的物品中选取,如此重复,直至求得满足条件的解,或者无解。

2.3 主要算法和处理流程图1.输入物品总个数2.依次输入各物品的体积3.输入背包总体积4.将物品排成一列,按顺序选取物品装入背包中,当物品太大不能装入时则弃之继续选取下一件,直到背包装满为止,5.出现在剩余的物品中找不到合适的物品填满背包的情况是说明刚刚装入背包的那件物品不适合,将它取出后继续选取后面的物品。

6.重复步骤4和5直至求出满足条件的解或者无解。

0-1背包问题动态规划详解及代码

0-1背包问题动态规划详解及代码

0/1 背包问题动态规划详解及C代码动态规划是用空间换时间的一种方法的抽象。

其关键是发现子问题和记录其结果。

然后利用这些结果减轻运算量。

比如01背包问题。

/* 一个旅行者有一个最多能用M公斤的背包,现在有N件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为P1,P2,...,Pn.若每种物品只有一件求旅行者能获得最大总价值。

输入格式:M,NW1,P1W2,P2......输出格式:X*/因为背包最大容量M未知。

所以,我们的程序要从1到M一个一个的试。

比如,开始任选N 件物品的一个。

看对应M的背包,能不能放进去,如果能放进去,并且还有多的空间,则,多出来的空间里能放N-1物品中的最大价值。

怎么能保证总选择是最大价值呢?看下表。

测试数据:10,33,44,55,6c[i][j]数组保存了1,2,3号物品依次选择后的最大价值.这个最大价值是怎么得来的呢?从背包容量为0开始,1号物品先试,0,1,2,的容量都不能放.所以置0,背包容量为3则里面放4.这样,这一排背包容量为4,5,6,....10的时候,最佳方案都是放4.假如1号物品放入背包.则再看2号物品.当背包容量为3的时候,最佳方案还是上一排的最价方案c为4.而背包容量为5的时候,则最佳方案为自己的重量5.背包容量为7的时候,很显然是5加上一个值了。

加谁??很显然是7-4=3的时候.上一排 c3的最佳方案是4.所以。

总的最佳方案是5+4为9.这样.一排一排推下去。

最右下放的数据就是最大的价值了。

(注意第3排的背包容量为7的时候,最佳方案不是本身的6.而是上一排的9.说明这时候3号物品没有被选.选的是1,2号物品.所以得9.)从以上最大价值的构造过程中可以看出。

f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n,m)}这就是书本上写的动态规划方程.这回清楚了吗?下面是实际程序(在VC 6.0环境下通过):#include<stdio.h>int c[10][100];/*对应每种情况的最大价值*/int knapsack(int m,int n){int i,j,w[10],p[10];printf("请输入每个物品的重量,价值:\n");for(i=1;i<=n;i++)scanf("%d,%d",&w[i],&p[i]);for(i=0;i<10;i++)for(j=0;j<100;j++)c[i][j]=0;/*初始化数组*/for(i=1;i<=n;i++)for(j=1;j<=m;j++){if(w[i]<=j) /*如果当前物品的容量小于背包容量*/{if(p[i]+c[i-1][j-w[i]]>c[i-1][j])/*如果本物品的价值加上背包剩下的空间能放的物品的价值*//*大于上一次选择的最佳方案则更新c[i][j]*/c[i][j]=p[i]+c[i-1][j-w[i]];elsec[i][j]=c[i-1][j];}else c[i][j]=c[i-1][j];}return(c[n][m]);}int main(){int m,n;int i,j;printf("请输入背包的承重量,物品的总个数:\n");scanf("%d,%d",&m,&n);printf("旅行者背包能装的最大总价值为%d",knapsack(m,n)); printf("\n");return 0;}。

01背包问题回溯法c语言

01背包问题回溯法c语言

01背包问题回溯法c语言背包问题是一个很经典的动态规划问题,其中最常见的一种形式就是 01 背包问题。

在该问题中,给定一组物品的重量和价值,以及一个背包的容量限制,要求选择一些物品,使得在不超过背包容量的前提下,背包中物品的总价值最大。

这里我们将讨论如何使用回溯法解决01 背包问题,使用C 语言进行编程实现。

首先,我们需要定义问题的数据结构。

我们可以使用一个数组来表示不同物品的重量和价值,背包的容量可以通过一个常量来表示。

```c#define N 5 // 物品的个数#define MAX_WEIGHT 10 // 背包的容量int weights[N] = {2, 3, 4, 5, 9}; // 物品的重量int values[N] = {3, 4, 5, 8, 10}; // 物品的价值int bestValue = 0; // 最优解的价值int bestSelection[N]; // 最优解中物品的选择情况```接下来,我们可以定义一个递归函数来实现回溯法。

该函数将遍历所有可能的物品选择情况,并更新当前的最优解。

```cvoid backtrack(int depth, int weight, int value, int selection[]) {if (depth == N) {if (weight <= MAX_WEIGHT && value > bestValue) {bestValue = value;for (int i = 0; i < N; i++) {bestSelection[i] = selection[i];}}return;}// 不选择当前物品selection[depth] = 0;backtrack(depth + 1, weight, value, selection);// 选择当前物品selection[depth] = 1;backtrack(depth + 1, weight + weights[depth], value + values[depth], selection); }```最后,我们可以在主函数中调用回溯函数,得到最优解。

动态规划之01背包问题

动态规划之01背包问题

动态规划之01背包问题01背包问题问题描述:给定 n 件物品,物品的重量为 w[i],物品的价值为 c[i]。

现挑选物品放⼊背包中,假定背包能承受的最⼤重量为 V,问应该如何选择装⼊背包中的物品,使得装⼊背包中物品的总价值最⼤?针对这个问题,本⼈理解了多次,也了看各种题解,尝试各种办法总还觉得抽象;或者说,看了多次以后,只是把题解的状态转移⽅程记住了⽽已,并没有真正的“掌握”其背后的逻辑。

直到我看了,在此感谢作者并记录于此。

01背包问题之另⼀种风格的描述:假设你是⼀个⼩偷,背着⼀个可装下4磅东西的背包,你可以偷窃的物品如下:为了让偷窃的商品价值最⾼,你该选择哪些商品?暴⼒解法最简单的算法是:尝试各种可能的商品组合,并找出价值最⾼的组合。

这样显然是可⾏的,但是速度⾮常慢。

在只有3件商品的情况下,你需要计算8个不同的集合;当有4件商品的时候,你需要计算16个不同的集合。

每增加⼀件商品,需要计算的集合数都将翻倍!对于每⼀件商品,都有选或不选两种可能,即这种算法的运⾏时间是O(2ⁿ)。

动态规划解决这样问题的答案就是使⽤动态规划!下⾯来看看动态规划的⼯作原理。

动态规划先解决⼦问题,再逐步解决⼤问题。

对于背包问题,你先解决⼩背包(⼦背包)问题,再逐步解决原来的问题。

⽐较有趣的⼀句话是:每个动态规划都从⼀个⽹格开始。

(所以学会⽹格的推导⾄关重要,⽽有些题解之所以写的不好,就是因为没有给出⽹格的推导过程,或者说,没有说清楚为什么要”这样“设计⽹格。

本⽂恰是解决了我这⽅⾯长久以来的困惑!)背包问题的⽹格如下:⽹格的各⾏表⽰商品,各列代表不同容量(1~4磅)的背包。

所有这些列你都需要,因为它们将帮助你计算⼦背包的价值。

⽹格最初是空的。

你将填充其中的每个单元格,⽹格填满后,就找到了问题的答案!1. 吉他⾏后⾯会列出计算这个⽹格中单元格值得公式,但现在我们先来⼀步⼀步做。

⾸先来看第⼀⾏。

这是吉他⾏,意味着你将尝试将吉他装⼊背包。

动态规划——背包问题1:01背包

动态规划——背包问题1:01背包

动态规划——背包问题1:01背包背包问题是动态规划中的⼀个经典题型,其实,也⽐较容易理解。

当你理解了背包问题的思想,凡是考到这种动态规划,就⼀定会得很⾼的分。

背包问题主要分为三种:01背包完全背包多重背包其中,01背包是最基础的,最简单的,也是最重要的。

因为其他两个背包都是由01背包演变⽽来的。

所以,学好01背包,对接下来的学习很有帮助。

废话不多说,我们来看01背包。

01 背包问题:给定 n 种物品和⼀个容量为 C 的背包,物品 i 的重量是 wi,其价值为 vi 。

问:应该如何选择装⼊背包的物品,使得装⼊背包中的物品的总价值最⼤?第⼀眼看上去,我们会想到贪⼼(背包问题还不会QAQ)。

⽤贪⼼算法来看,流程是这样的:1.排序,按价值从⼤到⼩排序2.选价值尽可能⼤的物品放⼊。

但是,贪⼼做这题是错的。

让我们举个反例:n=5,C=10重量价值第⼀个物品:105第⼆个物品:14第三个物品:23第四个物品:32第五个物品:41⽤贪⼼⼀算。

答案是5,但正解是⽤最后4个,价值总和是10.那将重量排序呢?其实也不⾏。

稍微⼀想就想到了反例。

我们需要借助别的算法。

贪⼼法⽤的是⼀层循环,⽽数据不保证在⼀层循环中得解,于是,我们要采⽤⼆层循环。

这也是背包的思想之⼀。

来看背包算法:1.⽤⼆维数组dp [ i ] [ j ],表⽰在⾯对第 i 件物品,且背包容量为 j 时所能获得的最⼤价值⽐如说上⾯的那个反例:dp [ 1 ] [ 3 ] = 4 + 3 = 7.2.01背包之所以叫“01”,就是⼀个物品只能拿⼀次,或者不拿。

那我们就分别来讨论拿还是不拿。

(1)j < w[i] 的情况,这时候背包容量不⾜以放下第 i 件物品,只能选择不拿dp [ i ] [ j ] = dp [ i - 1 ] [ j ];(2)j>=w[i] 的情况,这时背包容量可以放下第 i 件物品,我们就要考虑拿这件物品是否能获取更⼤的价值。

动态规划之01背包和完全背包

动态规划之01背包和完全背包

0-1背包状态转移方程:f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。

如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。

优化空间复杂度后得到:for i=1..Nfor v=V..0f[v]=max{f[v],f[v-c[i]]+w[i]};其中的f[v]=max{f[v],f[v-c[i]]}一句恰就相当于我们的转移方程f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]},因为现在的f[v-c[i]]就相当于原来的f[i-1][v-c[i]]。

procedure ZeroOnePack(cost,weight)for v=V..costf[v]=max{f[v],f[v-cost]+weight}注意这个过程里的处理与前面给出的伪代码有所不同。

前面的示例程序写成v=V..0是为了在程序中体现每个状态都按照方程求解了,避免不必要的思维复杂度。

而这里既然已经抽象成看作黑箱的过程了,就可以加入优化。

费用为cost的物品不会影响状态f[0..cost-1],这是显然的。

有了这个过程以后,01背包问题的伪代码就可以这样写:for i=1..NZeroOnePack(c[i],w[i]);如果是要求恰好装满背包,那么在初始化时除了f[0]为0其它f[1..V]均设为-∞,这样就可以保证最终得到的f[N]是一种恰好装满背包的最优解。

如果并没有要求必须把背包装满,而是只希望价格尽量大,初始化时应该将f[0..V]全部设为0。

背包问题的三种解法代码实现

背包问题的三种解法代码实现

背包问题的三种解法实验报告实验要求:分别用动态规划法、回溯法、分支限界法解决0/1 背包问题,了解三种算法的算法步骤并上机实现。

实验步骤:1. 建立一个背包问题的解法类Bag.h。

bag_m为动态规划法,bag_b为回溯法,bag_t为分支限界法。

2. 建立一个排序类Sort1.h。

程序的需要对背包的价值比排序。

3. 由分支限界建立一个动态的最大堆及堆的各种操作和运算类SqList.h。

代码实现:1. 主函数:// 背包问题的解法#include <iostream> #include "Bag.h"// 背包问题处理方法类using namespace std;int main() int i,n,M;coutvv"请输入物品个数:";cin>>n;double *m=new double[n+1];double *p=new double[n+1];coutvv"输入每个物品的重量:";for(i=1;i<=n;i++)cin>>m[i];coutvv"输入每个物品的价值:for(i=1;i<=n;i++)cin>>p[i];coutvv"请输入背包的重量:";cin>>M;Bag bag;//创建一个背包问题的解法类对象coutvv"选择背包问题的解法,输入1,动态规划法,输入2,回溯法,输入3,分支限界法。

"vv'\n'vv"请输入1或者2,或者输入3:"<<"";cin>>i;if(i==1)bag.bag_m(m, p,n,M);//调用动态规划法if(i==2)bag.bag_b(m, p,n,M);// 调用回溯法if(i==3)bag.bag_t(m, p,n ,M);//调用分支限界法return 0;2. 排序方法类:(Filename:Sort1.h)// 合并排序类(合并排序)#include <iostream>using namespace std;struct objdouble m;double p;double v;};typedef struct obj OBJ; // 定义物体的数据结构class Sort1public:void merge_sort(OBJ a[],int n)// 以物体的价值比排序int i,s,t=1;while(t<n)s=t;t=2*s;i=0;while(i+t<n)merge(a,i,i+s-1,i+t-1,t);i=i+t;if(i+s<n)merge(a,i,i+s-1,n-1,n-i);void merge(OBJ a[],int p,int q,int r,int n)OBJ *bp=new OBJ[n];int i,j,k;i=p;j=q+1;k=0;while(i<=q&&j<=r)if(a[i].v<=a[j].v)bp[k++]=a[i++];elsebp[k++]=a[j++];if(i==q+1)for(;j<=r;j++)bp[k++]=a[j];elsefor(;i<=q;i++)bp[k++]=a[i];k=0;for(i=p;i<=r;i++)a[i]=bp[k++];delete bp;};3. 背包问题解法类:(Filename:Bag.h)// 背包问题方法类(包含三种方法)//bag_m 动态规划法//bag_b 回溯法//bag_t 分支限界法#include <iostream>using namespace std;#include "Sort1.h"#include "SqList.h"class Bagpublic:void bag_m(double *m,double *p,int n,int M)// 动态规划法int i,j;int *x=new int[n+1];OBJ *objs=new OBJ[n+1];objs[0].p=0;objs[0].v=0;for(i=1;i<=n;i++)objs[i].m=m[i];objs[i].p=p[i];objs[i].v=objs[i].m/objs[i].p;double **optp;optp=new double *[n+1]; for(i=0;i<n+1;i++)optp[i]=new double[M+1]; x[i]=0;for(i=0;i<=n;i++)optp[i][0]=0;for(i=0;i<=M;i++)optp[0][i]=0;for(i=1;i<=n;i++)for(j=1;j<=M;j++)optp[i][j]=optp[i-1][j];elseoptp[i][j]=optp[i-1][j];if(optp[i][j]<(optp[i-1][int(j-objs[i].m)]+objs[i].p)) optp[i][j]=(optp[i-1][int(j-objs[i].m)]+objs[i].p);i=n;j=M;while(i&&j)if(optp[i][j]>optp[i-1][j])x[i]=1;j-=objs[i].m;elsex[i]=0;cout<<" 输出结果,装入为1,不装入为0:"<<'\n'; for(i=1;i<=n;i++)cout<<x[i]<<" ";}cout<<'\n';coutvv"背包物体的总价值最大为:"VVO ptp[n ][M]VV'\n:delete x,objs;for(i=0;i<=n;i++)delete [] optp[i];delete optp;void bag_b(double *m,double *p,int n,int M)// 回溯法int i,j,k;int *x=new int[n+1];int *y=new int[n+2];double m_cur,m_est,p_cur,p_est,p_total;m_cur=0;p_cur=0;p_total=0;OBJ *objs=new OBJ[n+1];objs[0].m=0;objs[0].p=0;objs[0].v=0;for(i=1;i<=n;i++)objs[i].m=m[i];objs[i].p=p[i];objs[i].v=objs[i].m/objs[i].p;y[i]=0;x[i]=0;y[n+1]=0;Sort1 sort;sort.merge_sort(objs,n+1);// 排序k=1;while(k>=1)p_est=p_cur;m_est=m_cur;for(i=k;i<=n;i++)m_est=m_est+objs[i].m;if(m_est<M)p_est=p_est+objs[i].p;elsep_est=p_est+((M-m_est+objs[i].m)/objs[i].m)*objs[i].p;break; if(p_est>p_total)for(i=k;i<=n;i++)if(m_cur+objs[i].m<=M) m_cur+=objs[i].m;p_cur+=objs[i].p;y[i]=1;else {y[i]=0; break;}if(i>=n)if(p_cur>p_total)p_total=p_cur;k=n+1; for(j=1;j<=n;j++)x[j]=y[j];else k=i+1;elsewhile(i>=1&&y[i]==0)if(i<1) break;elsem_cur-=objs[i].m;p_cur-=objs[i].p;y[i]=0;k=i+1;for(i=1;i<=n;i++)cout<<x[i];cout<<'\n';cout<<"total="<<p_total;delete x,y,objs;void bag_t(double *m,double *p,int n,int M)// 分支限界法int i;double t;OBJ *ob=new OBJ[n];for(i=0;i<n;i++)ob[i].m=m[i+1];ob[i].p=p[i+1];ob[i].v=ob[i].m/ob[i].p;Sort1 sort;sort.merge_sort(ob,n);Knapnode kn a,k nax,k nay;//定义左节点和右节点kna.b=0;kna.k=0;kna.p=0;kna.w=0;for(i=0;i<5;i++)kna.s1[i]=0;for(i=kna.k,t=kna.w;i<n;i++)if(t+ob[i].m<=M)t+=ob[i].m;kna.b+=ob[i].p;elsekna.b+=(M-t)*ob[i].p/ob[i].m;break;sqlist q;SqList sq;sq.InitList_Sq(q);sq.insert(q,kna);while(q.length!=0)kna=sq.delete_max(q);if(kna.k==5)}}cout<<"the value is:"<<kna.p<<'\n'; for(i=0;i<5;i++)cout<<kna.s1[i]<<" ";cout<<'\n';break;knay=kna;knay.k++;knay.b=knay.p;for(i=knay.k,t=knay.w;i<n;i++)if(t+ob[i].m<=M)t+=ob[i].m;knay.b+=ob[i].p;elseknay.b+=(M-t)*ob[i].p/ob[i].m;break;sq.insert(q,knay);knax=kna;if(knax.w+ob[knax.k].m>M)continue;knax.s1[knax.k]=1;knax.w+=ob[knax.k].m;knax.p+=ob[knax.k].p;knax.k++;sq.insert(q,knax);};4.动态堆方法类(分支限界方法中用到,Filename:SqList.h)// 动态最大堆#include <iostream>#include "math.h"#include <iomanip>using namespace std;#define ListInitSize 20#define ListIncrement 10const n=5;typedef structint s1[n];int k;float b;float w;float p;}Knapnode;typedef struct sqListKnapnode *elem;int length;int listsize;}sqlist;class SqList/动态堆类public:void InitList_Sq(sqlist &L)//n 为单位元素的大小,初始化堆L.elem=(Knapnode *)malloc(ListInitSize* sizeof(Knapnode));if(L.elem==NULL) exit(OVERFLOW);L.length=0;L.listsize=ListInitSize;void ListI nsert_Sq(sqlist & L,K napn ode elem)/向堆中插入节点Knapnode * newbase;if(L.length>=L.listsize)newbase=(Knapnode*)realloc(L.elem,(L.listsize+ListIncrement)sizeof(Knapnod e))if(newbase==NULL) exit(OVERFLOW);L.elem=newbase;L.listsize+=ListIncrement;L.elem[++L.length]=elem;void sift_up(sqlist &L,int i)// 上移操作while(i>=2)*if(L.elem[i].b>L.elem[i/2].b)swap(L.elem[i/2],L.elem[i]);i/=2;else break;void sift_down(sqlist &L,int i)// 下移操作int done=0;i=2*i;while(done==0&&i<=L.length)if(i+1<=L.length&&L.elem[i+1].b>L.elem[i].b) i++;if(L.elem[i/2].b<L.elem[i].b)swap(L.elem[i/2],L.elem[i]);else done=1;void swap(Knapnode &a,Knapnode &b)Knapnode t;t=a;a=b;b=t;void in sert(sqlist & L,Kna pn ode x)//插入节点后,并排序ListInsert_Sq(L,x);sift_up(L,L.length);Kna pn ode delete_max(sqlist & L)//删除堆中预测价值的最大者Knapnode p;p=L.elem[1];swap(L.elem[1],L.elem[L.length]);L.length--;sift_down(L,1);return p;void print(sqlist &L)// 打印堆的数据int i;};for(i=1;i<=L.length;i++)cout<<L.elem[i].b;运行方法和结果(用这三种算法分别给出实验结果):1. 动态规划法:2. 回溯法:3. 分支限界法。

动态规划之01背包问题(含代码C)

动态规划之01背包问题(含代码C)
V[0][j] = 0; for (i = 0; i < n; i++){
for (j = 0; j < C+1; j++){ if (j<w[i]) V[i][j] = V[i - 1][j]; else V[i][j] = max(V[i - 1][j], V[i - 1][j - w[i]] + v[i]);
4.动态规划的时间效率为O(nc)其中n表示物品的个数,c表示背包的容量。空间的效率就是用于存储二维数组的占用空间大小,即为O(nc).
5.代码如下所示:
#include<stdio.h> #include<cstdlib> int V[200][200];//前i个物品装入容量为j的背包中获得的最大价值 int max(int a, int b) {
适合于用动态规划法求解的问题经分解后得到的子问题往往不是互相独立的即下一个子阶段的求解是建立在上一个子阶段的解的基础上进行进一步的求解
动态规划之 01背包问题(含代码 C)
1.动态规划的基本思想
动态规划算法通常用于求解具有某种最优性质的问题。其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些 子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解 这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出 已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被 用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格 式。 与分治法最大的差别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立 在上一个子阶段的解的基础上,进行进一步的求解)

分支界线法01背包问题c语言

分支界线法01背包问题c语言

分支界线法01背包问题c语言一、问题描述01背包问题是常见的动态规划问题,其描述如下:有一个背包,最多能承载重量为W的物品。

现在有n个物品,其重量分别为w1, w2, ..., wn,价值分别为v1, v2, ..., vn。

要求选取若干物品放入背包,使得放入背包的物品总价值最大,且总重量不超过W。

二、分支界线法思想分支界线法是一种求解组合优化问题的常用方法。

在01背包问题中,分支界线法的思想是通过一个优先级队列,不断生成和扩展状态空间树,记录每个节点的上界评价函数值,并根据上界值进行搜索剪枝,直至获得最优解。

三、算法步骤1. 定义物品结构体```ctypedef struct {double value; // 物品价值double weight; // 物品重量double unitValue; // 物品单位价值} Item;```2. 比较函数定义(用于优先级队列)```cintpare(const void* a, const void* b) {Item* itemA = (Item*)a;Item* itemB = (Item*)b;double diff = itemB->unitValue - itemA->unitValue; return diff < 0 ? -1 : diff > 0 ? 1 : 0;}```3. 分支界线法求解01背包问题```cdouble knapsack(int n, double W, Item* items) {qsort(items, n, sizeof(Item),pare);double maxValue = 0;double currentWeight = 0;for (int i = 0; i < n; i++) {if (currentWeight + items[i].weight <= W) {currentWeight += items[i].weight;maxValue += items[i].value;} else {double rem本人nWeight = W - currentWeight;maxValue += items[i].unitValue * rem本人nWeight;break;}}return maxValue;}```四、代码实现解释1. 首先根据物品单位价值对物品进行排序,通过单位价值可以快速确定选择哪个物品放入背包;2. 依次选择单位价值最高的物品放入背包,若背包容量不足则按部分放入;3. 根据剩余容量,估算能够放入的最大价值。

【CC++】01背包问题动态规划

【CC++】01背包问题动态规划
for (int i = 1; i <= n; i++) {
for(int j = 1; j <= V; j++) {
if (j < vw[i-1][0]) {
dp[i][j] = dp[i-1][j]; } else {
dp[i][j] = max(dp[i-1][j], dp[i-1][j-vw[i-1][0]] + vw[i-1][1]); } } // for (int j = vw[i-1][0]; j <= V; j++) // { // dp[i][j] = max(dp[i-1][j], dp[i-1][j-vw[i-1][0]] + vw[i-1][1]); // } } int maxx = 0;
【 CC++】 01背包问题动态规划
按小蓝书上写的大数据情况下没过,按解答区一个大佬的修改了过了
#include <bits/stdc++.h> using namespace std;
class Solution { public:
/** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * 计算01背包问题的结果 * @param V int整型 背包的体积 * @param n int整型 物品的个数 * @param vw int整型vector<vector<>> 第一维度为n,第二维度为2的二维数组,vw[i][0],vw[i][1]分别描述i+1个物品的vi,wi * @return int整型 */ int knapsack(int V, int n, vector<vector<int>>& vw) {

01背包问题与动态规划(DP)

01背包问题与动态规划(DP)

01背包问题与动态规划(DP)解法⼀:我们先⽤最朴素的⽅法,着眼于每个物体是否进⼊背包,进⾏遍历。

代码如下:#include<iostream>#include<algorithm>using namespace std;int N,W;const int maxn=105;int v[maxn],w[maxn];int rec(int i,int j){//从第i个下标开始,计算剩余j重量怎么挑选商品int ans;if(i==N) ans=0;//已经没有商品可以选择else if(j<w[i]) ans=rec(i+1,j);//如果背包容量装不下下标为i的商品else ans=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);return ans;}int main(){cin>>N>>W;for(int i=0;i<N;i++) cin>>w[i];for(int i=0;i<N;i++) cin>>v[i];int res=rec(0,W);cout<<res<<endl;return0;}然⽽这种算法是对每个商品都进⾏处理,每⼀层搜索都有两个分⽀,时间复杂度为O(2^n),当n⽐较⼤的时候就会花费较多的时间。

我们注意到,对每个商品进⾏搜索的时候,有时会出现相同的参数,于是第⼆次调⽤的时候我们其实已经计算过⼀次了,等于是⽩⽩浪费了时间。

所以我们有了新的想法:把第⼀次计算的结果给记录下来,这样可以省下不少时间。

于是有了解法⼆:⽤⼀个⼆维数组记录下之前第⼀次计算出的结果,等到第⼆次调⽤相同参数函数的时候,就不必计算。

1 #include<iostream>2 #include<algorithm>3 #include<cstring>4using namespace std;5const int maxN=3405;6const int maxW=405;7int dp[maxN][maxW];8int N,W;9int w[maxW],v[maxN];10int rec(int i,int j){11if(dp[i][j]>=0) return dp[i][j];12int ans;13if(i==N) ans=0;14else if(j<w[i]) ans=rec(i+1,j);15else ans=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);16return dp[i][j]=ans;17 }18int main(){19 memset(dp,-1,sizeof(dp));20 cin>>N>>W;21for(int i=0;i<N;i++)22 {23 cin>>w[i];24 cin>>v[i];25 }26int res=rec(0,W);27 cout<<res<<endl;28return0;29 }30观察这个记忆化数组,我们如果把dp[i][j]定义成如下意义:当总重量⼩于j时,从下标为i的商品开始挑选,得到商品的最⼤值。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档