您的当前位置:首页正文

【PTA】K-背包问题

2024-11-23 来源:个人技术集锦

题目来源

问题描述

给定 n ( n < = 100 ) n(n<=100) n(n<=100)种物品和一个背包。物品 i i i的重量是 w i w_i wi,价值为 v i v_i vi,背包的容量为 C ( C < = 1000 ) C(C<=1000) C(C<=1000)。问:应如何选择装入背包中的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有两个选择:装入或不装入。不能将物品 i i i装入多次,也不能只装入部分物品 i i i

输入格式:
共有 n + 1 n+1 n+1行输入: 第一行为 n n n值和 c c c值,表示 n n n件物品和背包容量 c c c; 接下来的 n n n行,每行有两个数据,分别表示第 i ( 1 ≤ i ≤ n ) i(1≤i≤n) i(1in)件物品的重量和价值。
输出格式:
输出装入背包中物品的最大总价值。
输入样例:
在这里给出一组输入。例如:
5 10
2 6
2 3
6 5
5 4
4 6
输出样例:
在这里给出相应的输出。例如:
15

思路分析

这是一个K-背包问题,这里先列举一个例子解释下什么是K-背包问题。假设有一个小偷在商店里偷东西,但他的背包大小有限,只能一部分商品带走。每个商品不一样贵,问小偷如何赚的最多。如图所示,假设商店里有4件商品,每件的重量分别是3,5,4,9,价格分别是4,8,5,10。小偷的背包容纳的重量不超过20,所以不能把所有商品拿走,必须选择拿或不拿。
我们用如下的关系来表示:

算法实现

java

import java.io.*;
import java.util.Scanner;

public class Main {
public static void main(String[] argc) throws IOException
	{
			Scanner sc = new Scanner(System.in);
			int N = sc.nextInt()+1; 
			int W = sc.nextInt()+1;
			//要预留1位0
			int[] w = new int[N];
			int[] v = new int[N];
			for (int i=1;i<N;i++) {
				w[i]=sc.nextInt();
				v[i]=sc.nextInt();
			}
			
			System.out.println(knapsack(N,W,w,v));
			sc.close();
	}

	public static int knapsack(int N, int W, int[] w, int[] v) {
		int k, C;
		int[][] B = new int[N][W];// B自动初始化为0
		// k表示商品总数,在这里用于模拟从0到N的情况
		// C表示当背包容纳的重量,在这里C从1累加到W,用于模拟不同的背包大小
		for (k = 1; k < N; k++) {
			for (C = 1; C < W; C++) {
				if (w[k] > C) {// 如果第k件太重,则不偷,B不变
					B[k][C] = B[k - 1][C];
				} else {
					int value1 = B[k - 1][C - w[k]] + v[k]; // 偷第k件的总收益
					int value2 = B[k - 1][C]; // 不偷第k件的总收益
					if (value1 > value2) {
						// 选择偷和不偷的最大值
						B[k][C] = value1;
					} else {
						B[k][C] = value2;
					}
				}
			}
		}
		return B[N-1][W-1];
	}
}
显示全文