有N件物品和一个容量为V的背包。第i件物品的价值是C[i],重量是W[i]。求解将哪些物品装入背包可使价值总和最大。
输入第一行数 N V (1 <=N <=500) (1<= V <= 10000)
输入 N行 两个数字 代表 C W (1 <= C <= 50000, 1 <= W <=10000)
输出最大价值
5 10 8 6 10 4 4 2 5 4 5 3
19
1 1 10 2
0
import sys N,V = map(int,sys.stdin.readline().split()) values = [0]*(N+1) weights = [0]*(N+1) i = 1 for line in sys.stdin.readlines(): values[i],weights[i] = map(int,line.split()) i+=1 dp = [[0]*(V+1) for _ in range(N+1)] #dp[i][j] 面对第i个物品,背包容量为j时的价值最大值 for i in range(1,N+1): for j in range(1,V+1): if j>= weights[i]: dp[i][j] = max(dp[i-1][j],dp[i-1][j-weights[i]]+values[i]) else: dp[i][j] = dp[i-1][j] #不要这个东西,价值和i-1一样,容量不变 print(dp[-1][-1])
#include<iostream> #include<algorithm> #include<vector> using namespace std; int main() { int N, V; cin >> N>>V; vector<int> C(N + 1, 0); vector<int> W(C); for (int i = 1; i<=N; i++) cin >> C[i] >> W[i]; vector<vector<int>> dp(N + 1, vector<int>(V + 1,0)); for(int i=1;i<=N;i++)//i是物品号,从1开始 N是背包容量 for (int j = 1; j <= V; j++) { if (j < W[i])//装不下 dp[i][j] = dp[i - 1][j]; else { dp[i][j] = max(dp[i - 1][j], (dp[i - 1][j - W[i]] + C[i])); } } cout << dp[N][V]; }
n,v=map(int,input().split()) c=[0 for i in range(n)] w=[0 for i in range(n)] for i in range(n): c[i],w[i]=map(int,input().split()) def package (n,v,c,w): d=[[0 for i in range(v+1)] for j in range(n+1)] for i in range(1,n+1): for j in range(1,v+1): if j>=w[i-1]: d[i][j]=max(d[i-1][j],d[i-1][j-w[i-1]]+c[i-1]) else: d[i][j]=d[i-1][j] #return max(map(max,d)) return d[-1][-1] print(package(n,v,c,w))
#include<iostream> #include<vector> #include<algorithm> using namespace std; int main(){ int N,V=0; while(cin>>N>>V){ vector<int> c(N); vector<int> w(N); for(int i=0;i<N;++i){ cin>>c[i]>>w[i]; } vector<int> dp(V+1); for(int i=0;i<N;++i){ for(int j=V;j>=w[i];--j){ dp[j]=max(dp[j],dp[j-w[i]]+c[i]); } } cout<<dp[V]; } return 0; }
#include<iostream> using namespace std; #include<vector> int main() { int N,V; while(cin >> N >> V) { vector<int> value(N);//存储每个物品的价值 vector<int> capacity(N);//存储每个物品的容量 for(int i = 0; i < N; ++i) { cin >> value[i] >> capacity[i]; } vector<vector<int>> dp(N+1,vector<int>(V+1,0)); //有N+1行,但是从1开始遍历,所以每行表示每个物品 //有V+1列,但是从1开始遍历,所以每列表示从1开始到最大容量 的 各种情况下 的 物品最大价值存储 for(int i = 1; i < N+1; ++i) { for(int j = 1; j < V+1; ++j) { if(capacity[i-1] > j)//如果不下,那就等于上次的最优存储 {//这里的capacity[i-1]是因为这里的i从1开始 dp[i][j] = dp[i-1][j]; } else//如果能放下,有两种情况:1、放 2、不放 //放和不放取决于放了之后是否是最优的,于是创建一个临时变量。 {//dp[i-1][j-capacity[i-1]]:i-1:上面一行,j-capacity[i-1]:装了i-1这个物品之后还剩的容量。所以整体就是:当前的tmp_best == 装了i-1物品的价值 + 装了这个物品后剩余的容量还可以装的最优的方案 int tmp_best = value[i-1] + dp[i-1][j-capacity[i-1]]; dp[i][j] = max(tmp_best,dp[i-1][j]); } } } //返回最后一个元素就是最优的方案 cout << dp[N][V] << endl; } return 0; }
def bagvalue(c:list,w:list,v:int): if len(c)!=len(w)&nbs***bsp;len(c) == 0&nbs***bsp;len(w) == 0: return 0 return process(c,w,0,v) def process(c:list,w:list,index:int,v:int): if v < 0: return -1 if index == len(c): return 0 p1 = process(c,w,index+1,v) p2=0 nextindex = process(c,w,index+1,v - w[index]) if nextindex != -1: p2 = c[index] + nextindex return max(p1,p2) n,v = map(int,input().split()) c,w = [],[] for i in range(n): c1,w1 = map(int,input().split()) c.append(c1) w.append(w1) print(bagvalue(c,w,v))python动态规划解法:
def dp(c:list,w:list,v:int): n = len(c) #***重要!!!python数组定义方式用for循环 dp = [[0 for _ in range(v+1)]for _ in range(n+1)] for index in range(n-1,-1,-1): for rest in range(v+1): p1 = dp[index+1][rest] nextindex = -1 if rest-w[index] <0 else dp[index+1][rest-w[index]] p2 = 0 if nextindex != -1: p2 = c[index] + nextindex dp[index][rest] = max(p1,p2) return dp[0][v] n,v = map(int,input().split()) c,w = [],[] for i in range(n): c1,w1 = map(int,input().split()) c.append(c1) w.append(w1) print(dp(c,w,v))
import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); // String first = in.nextLine(); // String[] firstArray = first.split(" "); // int n = Integer.parseInt(firstArray[0]); // int c = Integer.parseInt(firstArray[1]); int n = in.nextInt(); int v = in.nextInt(); int[] values = new int[n+1]; int[] weights = new int[n+1]; // 注意 hasNext 和 hasNextLine 的区别 for (int i = 0; i < n; i++) { // 注意 while 处理多个 case values[i] = in.nextInt(); weights[i] = in.nextInt(); } // int[][] result = new int[n][v]; int result[][] = new int[n + 1][v + 1]; for (int i = 1; i < n + 1; i++) { for (int j = 1; j < v + 1; j++) { //使用动态转移方程对二维数组赋值 if (j < weights[i]) { result[i][j] = result[i - 1][j]; } else { result[i][j] = Math.max(result[i - 1][j], result[i - 1][j - weights[i]] + values[i]); } } } System.out.println(result[n][v]); // if (i == 0 || j == 0 ) { // dp[i][j] = 0; // continue; // } // if (bbc[i] < j) { // dp[i][j] = dp[i-1][j]; // } else { // dp[i][j] = Math.max(dp[i-1][j], dp[i-1][v] + bbw[i]); // } // } // } // System.out.println(dp[n][v]); } }
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); int n = sc.nextInt(); // n件物品 int v = sc.nextInt(); // 容量v int[] c = new int[n]; // 单件价值 int[] w = new int[n]; // 单间重量 for (int i = 0; i < n; i++) { c[i] = sc.nextInt(); w[i] = sc.nextInt(); } // int[][] dp = new int[n][v]; // 初始化第一行 for (int i = 0; i < v; i++) { if (i >= w[0]) { dp[0][i] = w[0]; } else { dp[0][i] = 0; } } // 遍历物品 for (int i = 1; i < n; i++) { // 遍历容量 for (int j = 0; j < v; j++) { if (j < w[i]) { // 空间不足 dp[i][j] = dp[i - 1][j]; } else { dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - w[i]] + c[i]); } } } System.out.println(dp[n-1][v-1]); sc.close(); }
python递归啰嗦版【既能保存下最大价值,同时还能保存下是哪些物品组合出当前的最大价值,因此,比较啰嗦,毕竟题目没有要求输出组合】
import sys count=0 param={} elements=[] for line in sys.stdin: a = line.split() if count==0: param["N"]=int(a[0]) param["V"]=int(a[1]) pass elif count<=param["N"]: single={} single["C"]=int(a[0]) single["W"]=int(a[1]) elements.append(single) pass else: break count += 1 # 最终要查询保存的表 共计N+1 行 下标从1开始 F=[[0 for j in range(param["V"]+1)] for i in range(param["N"]+1)] def getMaxOne(v:int,initList:list[dict],already:list[int])->list: # 获取单件物品最大价值 maxValue = 0 maxIndex = -1 for i in range(len(initList)): if i in already: continue item = initList[i] if item["W"]<=v and item["C"]>maxValue: maxValue = item["C"] maxIndex = i pass pass # F[1][V] if maxValue>0: F[1][v]=maxValue return [maxIndex] def calculateF(i:int,v:int,initList:list[dict],alreadyInput:list[int])->list: # 计算 i 个物品 V 的容量条件下的最大价值 if i==1: return getMaxOne(v,initList,alreadyInput) else: # F[i-1][V] already1 = calculateF(i-1,v,initList,alreadyInput) maxValue = F[i-1][v] alreadyOut = already1 # F[i-1, v − Wi] + Ci for iterNum in range(len(initList)): if iterNum in alreadyInput: continue item = initList[iterNum] C = item["C"] W = item["W"] if (v-W)<=0: continue alreadyTemp = [iterNum] alreadyTemp.extend(alreadyInput) already2 = calculateF(i-1,v-W,initList,alreadyTemp) if -1 in already2: continue twoPlus = F[i-1][v-W]+C already2.append(iterNum) if twoPlus>maxValue: maxValue = twoPlus alreadyOut = already2 pass F[i][v]=maxValue return alreadyOut pass already = calculateF(param["N"],param["V"],elements,[]) print(F[-1][-1])
最后的already就是最大价值使用的物品的下标
import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); //输入物品件数 int n = in.nextInt(); //输入背包容量 int v = in.nextInt(); //存放物品价值数组 int values[] = new int[n + 1]; //存放物品重量数组 int weights[] = new int[n + 1]; //初始化结果的二维数组 int result[][] = new int[n + 1][v + 1]; //向价值数组和重量数组存数 for(int i = 1;i < n + 1;i++){ values[i] = in.nextInt(); weights[i] = in.nextInt(); } //使用动态转移方程对二维数组赋值 for(int i = 1;i < n + 1;i++){ for(int j = 1;j < v + 1;j++){ if(j < weights[i]){ result[i][j] = result[i - 1][j]; }else{ result[i][j] = Math.max(result[i - 1][j],result[i - 1][j - weights[i]] + values[i]); } } } System.out.println(result[n][v]); } }
import sys # n: 物品数量 cap: 背包容量 n, cap = list(map(int, input().split())) # values: 物品价值 weights: 物品重量 values, weights = [], [] for _ in range(n): v, c = list(map(int, input().split())) values.append(v); weights.append(c) # 初始化 dp dp = [values[0] if c >= weights[0] else 0 for c in range(cap)] # 迭代 dp for i in range(n): for c in range(cap-1,weights[i]-1, -1): dp[c] = max(dp[c], dp[c - weights[i]] + values[i]) print(dp[-1])
#include<iostream> #include<algorithm> using namespace std; int V[10001]; //体积 - 最大价值数组 int main() { int N = 0;//物品数量 int backpack_size = 0; cin >> N >> backpack_size; while(N) { int w = 0; //质量 int v = 0; //价值 cin >> v >> w; for(int i = backpack_size; i >= w; --i) { if(w < backpack_size) V[i] = max(V[i] , V[i - w] + v); } --N; } cout << V[backpack_size]; return 0; }
import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int N = sc.nextInt(), V = sc.nextInt(); int[] wei = new int[N]; int[] val = new int[N]; for(int i = 0; i < N; i++){ val[i] = sc.nextInt(); wei[i] = sc.nextInt(); } int[] dp = new int[V + 1]; for(int i = 0; i < N; i++){ for(int j = V; j > 0; j--){ if(j >= wei[i]) dp[j] = Math.max(dp[j], dp[j - wei[i]] + val[i]); } } System.out.print(dp[V]); } }
// JS DP动态规划二维数组解决法: let [count, volume] = readline().split(" ").map(item => parseInt(item)); let valueAndWeight; let goodsList = []; while (valueAndWeight = readline()) { let list = valueAndWeight.split(" "); goodsList.push([parseInt(list[0]), parseInt(list[1])]); } // 按重量排序,第二列输入为重量 goodsList.sort((a, b) => a[1] - b[1]); // 得出 C、W 数组,需要填充第一个为0,对应容量为0 的情况 let cList = [0], wList = [0]; for (let k = 0; k < goodsList.length; k++) { cList.push(goodsList[k][0]); wList.push(goodsList[k][1]); } // 计算得出dp(dynamic programming)数组 let dpList = []; for (let i = 0; i < goodsList.length + 1; i++) { if (dpList[i] === undefined) { dpList[i] = []; } for (let j = 0; j < volume; j++) { dpList[i][j] = 0; if (i === 0 || j === 0) { // 填充第0行及第零列,避免动态转换公式 i - 1 和 j - 1 的情况 dpList[i][j] = 0; } else if (j < wList[i]) { // 拿不了当前物品的情况 dpList[i][j] = dpList[i - 1][j]; } else if (j >= wList[i]) { // 拿的了当前物品的情况 let gotJValue = cList[i] + dpList[i - 1][j - wList[i]]; // 拿当前物品得到的最大价值 = 当前物品价值 + 前面物品在剩余重量下的最大价值:value = dpList[i - 1][j - w[i]] + c[i] let noJValue = dpList[i - 1][j]; // 不拿当前物品的最大价值 = 前面物品在当前重量下的最大价值:value = dpList[i - 1][j] dpList[i][j] = Math.max(gotJValue, noJValue); } } } console.log(dpList[dpList.length - 1][dpList[dpList.length - 1].length - 1]);/** * 一维数组解法: * 空间优化为一维数组,滚动式数组,实际就是根据后无效原则,进行滚动式更新数组, * 原因是每轮滚动,数组实际只和上一轮数组有关,和再之前的 i - 2 序列的数组无关 */ let [count, volume] = readline().split(" ").map(item => parseInt(item)); let valueAndWeight; let goodsList = []; while (valueAndWeight = readline()) { let list = valueAndWeight.split(" "); goodsList.push([parseInt(list[0]), parseInt(list[1])]); } // 按重量排序,第二列输入为重量 // goodsList.sort((a, b) => a[1] - b[1]); // 得出 C、W 数组,需要填充第一个为0,对应容量为0 的情况 let cList = [0], wList = [0]; for (let k = 0; k < goodsList.length; k++) { cList.push(goodsList[k][0]); wList.push(goodsList[k][1]); } // 计算得出dp(dynamic programming)数组 let dpList = []; for (let i = 0; i < goodsList.length + 1; i++) { for (let j = volume; j >= 0; j--) { // *****重点:需要逆序递推,避免前序元素被早替换导致 dpList[j] = dpList[j] === undefined ? 0 : dpList[j]; if (j >= wList[i]) { // 拿的了当前物品的情况 let gotJValue = cList[i] + dpList[j - wList[i]]; // 拿当前物品得到的最大价值 = 当前物品价值 + 前面物品在剩余重量下的最大价值:value = dpList[j - w[i]] + c[i] let noJValue = dpList[j]; // 不拿当前物品的最大价值 = 前面物品在当前重量下的最大价值:value = dpList[j] dpList[j] = Math.max(gotJValue, noJValue); } } } console.log(dpList[dpList.length - 1]);
# python版递归解法 n, v = map(int, input().split()) C , W = [], [] for i in range(n): c, w = map(int, input().split()) C.append(c) W.append(w) total = 0 maxval = 0 def dfs(v, C, left): global maxval global total if left==[]&nbs***bsp;min(left)>v: if maxval>total: total = maxval return for i in range(len(left)): if left[i]<=v: v-=left[i] maxval+=C[i] temp_left = left[:] temp_C = C[:] temp_left.pop(i) temp_C.pop(i) dfs(v, temp_C, temp_left) maxval-=C[i] v+=left[i] dfs(v, C[:], W[:]) print(total)
//一维数组01背包问题 #include <iostream> #include <vector> using namespace std; int main() { int N, V; while(cin >> N >> V) { vector<int> dp(V + 1, 0); vector<int> C(N + 1, 0);//价值 vector<int> W(N + 1, 0);//重量 for(int i = 1; i <= N; i++) cin >> C[i] >> W[i]; for(int i = 1; i <= N; i++) { //此处已经进行了优化,背包重量小于当前物品的重量,则空包都放不进去,直接跳过 for(int j = V; j >= W[i]; j--) { dp[j] = dp[j] > dp[j - W[i]] + C[i] ? dp[j] : dp[j - W[i]] + C[i]; } } cout << dp[V] << endl; } return 0; }
N,V = map(int,input().split()) pro = [] dp = [] for i in range(N): pro.append(list(map(int,input().split()))) for i in range(N+1): dp.append([0 for i in range(V+1)]) for i in range(1,N+1): for j in range(V+1): if pro[i-1][1] > j : continue dp[i][j] = max(dp[i-1][j - pro[i-1][1]] + pro[i-1][0],dp[i-1][j]) print(dp[N][V])
#include <bits/stdc++.h> using namespace std; //01背包问题,最值问题 int main(){ int n, v; vector<vector<int> > goods(n, vector<int>(2, 0));//value,weight cin >> n >> v; for (int i = 0; i < n; i++) { cin >> goods[i][0] >> goods[i][1]; } vector<int> dp(v + 1, 0); for(int i = 1; i < goods.size(); i++) { for (int j = v; j >= goods[i][1]; j--) { dp[j] = max(dp[j], dp[j - goods[i][1]] + goods[i][0]); } } cout << dp[v]; return 0; }