第一行输入两个整数
代表预算、查询到的物品总数。
此后
行,第
行输入三个整数
代表第
件物品的价格、重要度、主件编号。特别地,
代表该物品为主件,否则表示该附件从属于主件
。编号即输入顺序,从
开始。
特别地,保证全部物品的价格
均为
的倍数;且每个主件的附件数不超过
个。
在一行上输出一个整数,代表王强可获得的最大满意度。
50 5 20 3 5 20 3 5 10 3 0 10 2 0 10 1 0
130
在这个样例中,第三、四、五件物品为主件,第一、二件物品为第五件物品的附件。这就意味着,如果购买了第一件物品或第二件物品,则必须购买第五件物品;但是特别地,如果同时购买了第一件物品和第二件物品,则只需要购买一次第五件物品。
我们可以证明,购买一、二、五件商品,获得的满意度最大,为
。
1000 5 800 2 0 400 5 1 300 5 1 400 3 0 500 2 0
2200
本题已于下方时间节点更新,请注意题解时效性:
1. 2025-05-15 更新题面,新增几组hack数据(暂未进行重测)。
2. 2024-12-13 更新题面。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Integer v = sc.nextInt() / 10;
Integer n = sc.nextInt();
// 录入一下商品
Map<Integer, List<Item>> itemMap = new HashMap<>();
for (int i = 1; i < n+1; i++) {
Integer itemV = sc.nextInt() / 10;
Integer itemM = sc.nextInt() * itemV;
Integer itemQ = sc.nextInt();
Item item = new Item(itemV, itemM, itemQ);
// 主件已自身序号为key,创建map
if (item.q == 0) {
List<Item> items = itemMap.computeIfAbsent(i, k->new ArrayList<>());
items.add(0, item);
} else {
// 附件以主件序号创建map
List<Item> items = itemMap.computeIfAbsent(itemQ, k->new ArrayList<>());
items.add(item);
}
}
// 动态规化
int[] dp = new int[v + 1];
itemMap.values().forEach(itemList -> {
for (int j = v; j > 0; j--) {
Item main = itemList.get(0);
List<Item> attachs = itemList.subList(1, itemList.size());
// 1.0 只买主件
if (j>= main.v) {
dp[j] = Math.max(dp[j], dp[j - main.v] + main.m);
}
// 2.0 一主一附
for (Item attach : attachs) {
// 钱必须足够
if (j >= main.v + attach.v) {
dp[j] = Math.max(dp[j], dp[j - main.v - attach.v] + main.m + attach.m);
}
}
// 3.0 一主多附
if (attachs.size() == 2 && j >= main.v + attachs.get(0).v + attachs.get(1).v) {
dp[j] = Math.max(dp[j], dp[j - main.v - attachs.get(0).v - attachs.get(1).v] + main.m + attachs.get(0).m + attachs.get(1).m);
}
}
});
System.out.println(dp[v] * 10);
}
static class Item {
public Integer v;
public Integer m;
public Integer q;
public Item(Integer v, Integer m, Integer q) {
this.v = v;
this.m = m;
this.q = q;
}
}
} import java.util.*;
/*
有依赖的背包问题
附件依赖于主件,其实还是选主件的问题,只是在不选和怎么选之间选择
设dp[i][j]表示前i件物品成本不超过j元时获得的最大满意度
只针对主件,x表示上一个主件的位置,遇到附件之间跳过
1)不选当前主件:dp[i][j]=dp[x][j]
2)只选主件:dp[i][j]=Math.max(第一种情况,dp[x][j-主件价格]+主件满意度)
3)选主件+附件1:dp[i][j]=Math.max(前两种情况,dp[x][j-主件价格-附件1价格]+主件满意度+附件1满意度)
4)选主件+附件2:dp[i][j]=Math.max(前三种情况,dp[x][j-主件价格-附件2价格]+主件满意度+附件2满意度)
5)选主件+附件1+附件2:dp[i][j]=Math.max(前四种情况,dp[x][j-主件价格-附件1价格-附件2价格]+主件满意度+附件1满意度+附件2满意度)
需要二维数组follows[][]存储主件对应的附件位置,方便在操作当前主件时能够找到对应的附件
*/
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
//输入总预算、物品个数
int n=in.nextInt();
int m=in.nextInt();
//输入各个物品的价格、重要度、编号
int []costs=new int [m];
int []value=new int [m];
int []points=new int [m];
for(int i=0;i<m;i++){
costs[i]=in.nextInt();
value[i]=costs[i]*in.nextInt();//直接计算满意度
points[i]=in.nextInt();
}
//follows记录主件的附件位置,初始化为-1
int [][]follows=new int [m][2];//最多只有两个附件
for(int []row:follows) Arrays.fill(row,-1);
for(int i=0;i<m;i++)
if(points[i]!=0){
//先判断第几个附件
//如果是第一个
if(follows[points[i]-1][0]==-1) follows[points[i]-1][0]=i;
else follows[points[i]-1][1]=i;
}
//开始背包
int [][]dp = new int [m+1][n+1];
dp[0][0]=0;
int x=0;
for(int i=1;i<=m;i++){
//不是主件直接跳过
if(points[i-1]!=0) continue;
for(int j=0;j<=n;j++){
//第一种情况,不选当前主件
dp[i][j]=dp[x][j];
//第二种情况,只选主件
if(j>=costs[i-1])
dp[i][j]=Math.max(dp[i][j],dp[x][j-costs[i-1]]+value[i-1]);//与第一种情况比较
//第三种情况,选主件+附件1(如果有的话)
if(follows[i-1][0]!=-1 && j>=costs[i-1]+costs[follows[i-1][0]])
dp[i][j]=Math.max(dp[i][j],dp[x][j-costs[i-1]-costs[follows[i-1][0]]]+value[i-1]+value[follows[i-1][0]]);//与第二种情况比较
//第四种情况,选主件+附件2(如果满足条件)
if(follows[i-1][1]!=-1 && j>=costs[i-1]+costs[follows[i-1][1]])
dp[i][j]=Math.max(dp[i][j],dp[x][j-costs[i-1]-costs[follows[i-1][1]]]+value[i-1]+value[follows[i-1][1]]);//与第三种情况比较
//第五种情况,选主件+附件1+附件2
if(follows[i-1][0]!=-1 && follows[i-1][1]!=-1 && j>=costs[i-1]+costs[follows[i-1][0]]+costs[follows[i-1][1]])
dp[i][j]=Math.max(dp[i][j],dp[x][j-costs[i-1]-costs[follows[i-1][0]]-costs[follows[i-1][1]]]+value[i-1]+value[follows[i-1][0]]+value[follows[i-1][1]]);
}
//当前的主件换成上一次的主件
x=i;
}
//最后输出最后一个主件的位置
System.out.print(dp[x][n]);
}
} import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 总钱数
int n = scanner.nextInt();
// 购买物品个数
int m = scanner.nextInt();
// 分组,goods[i]
Good[] goodList = new Good[m + 1];
//所有商品赋值
for (int i = 1; i <= m; i++) {
int v = scanner.nextInt();
int w = scanner.nextInt();
int q = scanner.nextInt();
goodList[i] = new Good(v, w, q);
//是否为主件
goodList[i].isMain = q == 0;
}
//遍历附件商品,赋给主件Good
for (Good good1 : goodList) {
if (good1 == null) {
continue;
}
if (good1.isMain) {continue;}
if (goodList[good1.q].subGood1 == null) {
goodList[good1.q].subGood1 = good1;
} else {
goodList[good1.q].subGood2 = good1;
}
}
//初始化动态规划数组 用以保存每个总价能得到的最大重要度
int[] dp = new int[n+1];
//再次遍历开始计算
for (Good good : goodList) {
if (good == null) {
continue;
}
//附件直接跳过
if (!good.isMain) {continue;}
//考虑所有组合可能性,分为四类:只要主件 主件+附件1 主件+附件2 主件+附件1+附件2
int v = good.v;
int ***bsp;= good.v * good.p;
int[][] cases = new int[4][2];
//只要主件
cases[0] = new int[]{v,***bsp; //主件+附件1
if (good.subGood1 != null) {
cases[1] = new int[]{v+good.subGood1.v,***bsp;+ (good.subGood1.v * good.subGood1.p)};
}
if (good.subGood2 != null) {
//主件+附件2
cases[2] = new int[]{v+good.subGood2.v,***bsp;+ (good.subGood2.v * good.subGood2.p)};
//主件+附件1+附件2
cases[3] = new int[]{v+good.subGood1.v+good.subGood2.v,***bsp;+ (good.subGood1.v * good.subGood1.p) + (good.subGood2.v * good.subGood2.p)};
}
//开始动态数组更新
for (int j = n; j >= 0; j--) {
for (int[] item : cases) {
int cost = item[0];
int value = item[1];
if (cost > 0 && j >= cost) {
dp[j] = Math.max(dp[j], dp[j - cost] + value);
}
}
}
}
System.out.println(dp[n]);
}
}
class Good {
int v; //价格
int p; //重要度
int q; //主件编号
boolean isMain;
Good subGood1;
Good subGood2;
public Good(int v, int p, int q) {
this.v = v;
this.p = p;
this.q = q;
}
} import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int budget=in.nextInt();
int n=in.nextInt();
if(n<=0||budget<=0){
System.out.println(0);
}
good[] g=new good[n+1];
for(int i=1;i<=n;i++){
int v=in.nextInt();
int w=in.nextInt();
int q=in.nextInt();
if(g[i]!=null){ //如果g[i] 对象已创建,则只需赋值,否则要实例化
g[i].setvwq(v,w,q);
}else{
g[i]=new good(v,w,q);
}
if(g[i].q>0){
//附件的主件对象未实例化时,先实例化
if(g[q]==null){
g[q]=new good(0,0,0);
}
g[q].setGood(g[i]);
}
}
int dp[][]=new int[n+1][budget/10 +1];
for(int i=1;i<=n;i++){
int v=0,v1=0,v2=0,v3=0,sa=0,sa1=0,sa2=0,sa3=0;
//只有主件(下一个循环语句中过滤掉附件)
v=g[i].v;
sa=g[i].v*g[i].w;
//主件+附件1
if(g[i].good1!=null){
v1=v+g[i].good1.v;
sa1=sa+g[i].good1.v*g[i].good1.w;
}
if(g[i].good2!=null){
//主件+附件2
v2=v+g[i].good2.v;
sa2=sa+g[i].good2.v*g[i].good2.w;
//主件+附件1+附件2
v3=v+g[i].good1.v+g[i].good2.v;
sa3=sa+g[i].good1.v*g[i].good1.w+g[i].good2.v*g[i].good2.w;
}
for(int j=1;j<=budget/10;j++){
if(g[i].q>0){ //附件跳过
dp[i][j]=dp[i-1][j];
}else{
dp[i][j]=dp[i-1][j];
if(j>=v/10&&v!=0) dp[i][j]=Math.max(dp[i][j],dp[i-1][j-v/10]+sa);
if(j>=v1/10&&v1!=0) dp[i][j]=Math.max(dp[i][j],dp[i-1][j-v1/10]+sa1);
if(j>=v2/10&&v2!=0) dp[i][j]=Math.max(dp[i][j],dp[i-1][j-v2/10]+sa2);
if(j>=v3/10&&v3!=0) dp[i][j]=Math.max(dp[i][j],dp[i-1][j-v3/10]+sa3);
}
}
}
System.out.println(dp[n][budget/10]);
}
public static class good{
int v;
int w;
int q;
good good1;
good good2;
public good(int v,int w,int q){
this.v=v;
this.w=w;
this.q=q;
}
public void setvwq(int v,int w,int q){
this.v=v;
this.w=w;
this.q=q;
}
public void setGood(good goodChild){
if(this.good1==null){
this.good1=goodChild;
}else if(this.good2==null){
this.good2=goodChild;
}
}
}
} import java.util.LinkedList;
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
static class Product{
public int v; //价格
public int w; //重要程度
public int q; //主件编号
public Product(int a,int b,int c){
v=a;w=b;q=c;
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int budget = scanner.nextInt(); //预算
int num = scanner.nextInt(); //商品数目
LinkedList<Product>[] list = new LinkedList[num]; //附件列表
for (int i = 0; i < num; i++) {
list[i] = new LinkedList<>();
}
Product[] products = new Product[num];
int[] dp = new int[budget+1]; //dp[i]代表的是i的预算去购买最大的满意度
for (int i = 0; i < num; i++) {
int v = scanner.nextInt();
int w = scanner.nextInt();
int q = scanner.nextInt();
products[i] = new Product(v,w,q);
if(q!=0){
list[q-1].add(products[i]);
}
}
//当前可购买的列表只有0-i个商品
for(int i=0;i<num;i++){ //一件一件增加商品类别
//只考虑主件,附件是主件自带的
if(products[i].q>0)
continue;
for (int j = budget; j >=0 ; j-- ) { //从后往前,可以防止重复购买i件商品
if(j>=products[i].v) //当前的钱可以购买第j件产品
{ // 选择购买当前第i件产品和不购买的满意度取max
dp[j] = Math.max(dp[j],dp[j-products[i].v]+products[i].v*products[i].w);
}
//主件+附件
if(list[i].size()>0&&j>=products[i].v+list[i].getFirst().v){
dp[j] = Math.max(dp[j],
dp[j-products[i].v-list[i].getFirst().v] + products[i].v*products[i].w + list[i].getFirst().v*list[i].getFirst().w);
}
if(list[i].size()>1&&j>=products[i].v+list[i].get(1).v){ //有两件附件
dp[j] = Math.max(dp[j],dp[j-products[i].v-list[i].get(1).v]+products[i].v*products[i].w+list[i].get(1).v*list[i].get(1).w);
}
if(list[i].size()>1&&j>=products[i].v+list[i].getFirst().v+list[i].get(1).v){
dp[j] = Math.max(dp[j],dp[j-products[i].v-list[i].getFirst().v-list[i].get(1).v]+products[i].v*products[i].w+list[i].get(1).v*list[i].get(1).w+list[i].getFirst().v*list[i].getFirst().w);
}
if(i==num-1)
break; //最后一件产品不需要计算前面的数值
}
}
System.out.println(dp[budget]);
}
}
package org.example;
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Shopping {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
int yuSuan = in.nextInt();
int goodsNum = in.nextInt();
int[][] goodsArr = new int[goodsNum][3];
for (int i = 0; i < goodsNum; i++) {
goodsArr[i][0] = in.nextInt();
goodsArr[i][1] = in.nextInt();
goodsArr[i][2] = in.nextInt();
}
//为每个主件维护一个链表,代表其不同的价值选项
ArrayList<HashMap<Integer, Integer>> mainGoodsMapList = new
ArrayList<HashMap<Integer, Integer>>();
for (int i = 0; i < goodsArr.length; i++) {
if (goodsArr[i][2] == 0) {
HashMap<Integer, Integer> valueMap = new HashMap<>();
valueMap.put(goodsArr[i][0], goodsArr[i][0] * goodsArr[i][1]);
int maxValue = goodsArr[i][0] ;
int maxSatisfaction = goodsArr[i][0] * goodsArr[i][1];
int fujianNum = 0;
for (int j = 0; j < goodsArr.length; j++) {
if (goodsArr[j][2] - 1 == i) {
fujianNum++;
maxValue += goodsArr[j][0];
maxSatisfaction += goodsArr[j][0] * goodsArr[j][1];
valueMap.put(goodsArr[i][0] + goodsArr[j][0],
goodsArr[i][0] * goodsArr[i][1] + goodsArr[j][0] * goodsArr[j][1]);
if (fujianNum == 2) {
valueMap.put(maxValue, maxSatisfaction);
}
}
}
mainGoodsMapList.add(valueMap) ;
}
}
int result = getMaxSatisfaction(mainGoodsMapList.size() - 1, mainGoodsMapList,
yuSuan);
System.out.println(result);
}
public static int getMaxSatisfaction(int newMainGoodsIndex, ArrayList<HashMap<Integer, Integer>> mainGoodsMapList , int yuSuan){
HashMap<Integer, Integer> newMainGoodsMap = mainGoodsMapList.get(newMainGoodsIndex);
if(newMainGoodsIndex == 0){
if(yuSuan <= 0){
return 0;
}
int result = 0;
int temp = 0;
for(int item:newMainGoodsMap.keySet()){
if(item <= yuSuan && newMainGoodsMap.get(item) > temp){
result = newMainGoodsMap.get(item);
}
}
return result;
}
else {
int lastMaxSatisfaction = getMaxSatisfaction(newMainGoodsIndex-1, mainGoodsMapList, yuSuan);
int currentMaxSatisfaction = lastMaxSatisfaction;
for(int item:newMainGoodsMap.keySet()){
if(item <= yuSuan){
currentMaxSatisfaction = Math.max(currentMaxSatisfaction, newMainGoodsMap.get(item) +
getMaxSatisfaction(newMainGoodsIndex-1, mainGoodsMapList, yuSuan-item)
);
}
}
return currentMaxSatisfaction;
}
}
} import java.util.ArrayList;
import java.util.Scanner;
/**
* Description:
* Author: fy
* Date: 2024/11/14 7:21
*/
public class Main {
static class Products {
int price;
int important;
int index;
public Products(int price, int important, int index) {
this.price = price;
this.important = important;
this.index = index;
}
@Override
public String toString() {
return "价格:" + price + " 重要度:" + important + " 索引:" + index;
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
String[] split = s.split(" ");
int amount = Integer.parseInt(split[0]);
int productCount = Integer.parseInt(split[1]);
ArrayList<Products> mainList = new ArrayList<>();
ArrayList<ArrayList<Products>> attachList = new ArrayList<>();
for (int i = 0; i < productCount; i++) {
attachList.add(new ArrayList<>());
}
int record = 0;
for (int i = 0; i < productCount; i++) {
String proStr = in.nextLine();
String[] proSplit = proStr.split(" ");
int price = Integer.parseInt(proSplit[0]);
int important = Integer.parseInt(proSplit[1]);
int mainProductIndex = Integer.parseInt(proSplit[2]);
int index = record;
if (mainProductIndex == 0) {
//存主件
Products products = new Products(price, important, index);
mainList.add(products);
} else {
//存附件
if (attachList.get(mainProductIndex - 1) == null) {
attachList.set(mainProductIndex - 1, new ArrayList<>());
}
Products products = new Products(price, important, index);
attachList.get(mainProductIndex - 1).add(products);
}
record++;
}
int[] dp = new int[amount + 1];
dp[0] = 0;
for (int i = 0; i < mainList.size(); i++) {
Products products = mainList.get(i);
int price = products.price;
int important = products.important;
int index = products.index;
for (int j = amount; j > 0; j--) {
//如果为空只考虑加或不加主件
if (attachList.get(index).isEmpty()) {
if (j >= price) {
dp[j] = Math.max(dp[j], dp[j - price] + important * price);
}
} else {
//如果有附件 先看看存不存主件
if (j >= price) {
dp[j] = Math.max(dp[j], dp[j - price] + important * price);
}
//在分别考虑 主件+附件1 和 主件+附件2 要不要为dp[j构成满意度
for (int k = 0; k < attachList.get(index).size(); k++) {
Products attachProducts = attachList.get(index).get(k);
int attachPrice = attachProducts.price;
int attachImportant = attachProducts.important;
if (j >= price + attachPrice) {
dp[j] = Math.max(dp[j], dp[j - price - attachPrice] + important * price +
attachImportant * attachPrice);
}
}
//如果有两个附件 还要考虑主件+两个附件 要不要为dp[j]构成满意度
if (attachList.get(index).size() > 1) {
Products attachProducts1 = attachList.get(index).get(0);
int attachPrice1 = attachProducts1.price;
int attachImportant1 = attachProducts1.important;
Products attachProducts2 = attachList.get(index).get(1);
int attachPrice2 = attachProducts2.price;
int attachImportant2 = attachProducts2.important;
int sumPrice = price + attachPrice1 + attachPrice2;
int sumImportant = important * price + attachImportant1 * attachPrice1 +
attachImportant2 * attachPrice2;
if (j >= sumPrice) {
dp[j] = Math.max(dp[j], dp[j - sumPrice] + sumImportant);
}
}
}
}
}
System.out.println(dp[amount]);
}
}
这是一个典型的0-1 背包问题的变种,其中存在主件和附件的约束关系。我们需要使用动态规划来解决这个问题。
主件和附件的关系:
目标:
思路:
package com.shisui.medium;
import java.util.*;
public class shopping_list {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt(); // 总钱数
int m = sc.nextInt(); // 物品个数
int[] dp = new int[N + 1]; // dp数组,dp[j]表示总价不超过j时的最大满意度
// 物品信息
Item[] items = new Item[m + 1];
List<Item>[] attachments = new List[m + 1];
// 初始化
for (int i = 0; i <= m; i++) {
attachments[i] = new ArrayList<>();
}
// 读取物品数据
for (int i = 1; i <= m; i++) {
int v = sc.nextInt();
int p = sc.nextInt();
int q = sc.nextInt();
items[i] = new Item(v, p, q);
if (q > 0) {
attachments[q].add(items[i]); // 把附件添加到对应的主件附件列表中
}
}
// 动态规划求解
for (int i = 1; i <= m; i++) {
if (items[i].q > 0) continue; // 处理附件时跳过
for (int j = N; j >= 0; j--) { // 从总钱数开始倒序遍历
// 主件选项
if (j >= items[i].v) {
dp[j] = Math.max(dp[j], dp[j - items[i].v] + items[i].v * items[i].p);
}
// 主件+附件1选项
if (attachments[i].size() >= 1 && j >= items[i].v + attachments[i].get(0).v) {
dp[j] = Math.max(dp[j], dp[j - items[i].v - attachments[i].get(0).v]
+ items[i].v * items[i].p
+ attachments[i].get(0).v * attachments[i].get(0).p);
}
// 主件+附件2选项
if (attachments[i].size() == 2 && j >= items[i].v + attachments[i].get(1).v) {
dp[j] = Math.max(dp[j], dp[j - items[i].v - attachments[i].get(1).v]
+ items[i].v * items[i].p
+ attachments[i].get(1).v * attachments[i].get(1).p);
}
// 主件+附件1+附件2选项
if (attachments[i].size() == 2 && j >= items[i].v + attachments[i].get(0).v + attachments[i].get(1).v) {
dp[j] = Math.max(dp[j], dp[j - items[i].v - attachments[i].get(0).v - attachments[i].get(1).v]
+ items[i].v * items[i].p
+ attachments[i].get(0).v * attachments[i].get(0).p
+ attachments[i].get(1).v * attachments[i].get(1).p);
}
}
}
System.out.println(dp[N]);
}
// 定义一个Item类来存储物品信息
static class Item {
int v; // 价格
int p; // 重要度
int q; // 0表示主件,其他表示附件所属主件的编号
public Item(int v, int p, int q) {
this.v = v;
this.p = p;
this.q = q;
}
}
}
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
// 物品类
private static class good{
public int v; // 物品价格
public int p; // 重要程度
public int q; // 是否是附件
public good a1 = null;
public good a2 = null;
public good(int v, int p, int q){
this.v = v;
this.p = p;
this.q = q;
}
public void setAppendGoods(good a){
if(this.a1 == null)
this.a1 = a;
else
this.a2 = a;
}
public boolean isFollowed(){
if(this.a1 == null && this.a2 == null)
return false;
else
return true;
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m = in.nextInt(); // 钱数
int n = in.nextInt(); // 购买物品数
List<good> input_good = new ArrayList<>(); // 存储输入值
List<good> input_follow_good = new ArrayList<>();
Map<Integer,Integer> map = new HashMap<Integer,Integer>(); // 存储主件位置
int totalCount = 0; // 记录主件原始数组中位置
int mainCount = 0; // 记录主件在主件数组中位置
while(in.hasNext()){
int v = in.nextInt();
int p = in.nextInt();
int q = in.nextInt();
if(q != 0)
input_follow_good.add(new good(v, p, q));
else{
input_good.add(new good(v, p ,q));
map.put(totalCount,mainCount);
mainCount++;
}
totalCount++;
}
int index = 0;
// 插入辅件
if(!input_follow_good.isEmpty()){
for(good g:input_follow_good){
index = map.get(g.q-1);
input_good.get(index).setAppendGoods(g);
}
}
int len = input_good.size();
int[][] dp = new int[m+1][len+1];
// 边界条件 - dp[0][j] = 0 | dp[i][0] = 0
// 辅件计算 - 0 选1 选2 两个都选
// 状态转换方程 (不带辅件)dp[i][j] = Max(dp[i][j-1], dp[i-input[j][0]][j-1] + input[j][0] * input[j][1]) (携带辅件)dp[i][j] = Max(dp[i][j-1], dp[i-input[j][0]][j-1] + input[j][0] * input[j][1], dp[i-input[j][0]-input[j1][0]][j-1] + input[j][0] * input[j][1] +input[j1][0] * input[j1][1], ***)
for(int i=1; i<m+1; i++){
for(int j=1; j<len+1; j++){
good temp = input_good.get(j-1);
dp[i][j] = dp[i][j-1];
if(i-temp.v >= 0){
dp[i][j] = Math.max(dp[i][j-1], dp[i-temp.v][j-1]+temp.v*temp.p);
if(temp.isFollowed()){
if(temp.a1 != null && i-temp.v-temp.a1.v >= 0) // 带附件1
dp[i][j] = Math.max(dp[i][j],dp[i-temp.v-temp.a1.v][j-1]+temp.v*temp.p+temp.a1.v*temp.a1.p);
if(temp.a2 != null && i-temp.v-temp.a2.v >= 0) // 带附件2
dp[i][j] = Math.max(dp[i][j],dp[i-temp.v-temp.a2.v][j-1]+temp.v*temp.p+temp.a2.v*temp.a2.p);
if(temp.a1 != null && temp.a2 != null && i-temp.v-temp.a1.v-temp.a2.v >= 0) // 带附件1和2
dp[i][j] = Math.max(dp[i][j],dp[i-temp.v-temp.a1.v-temp.a2.v][j-1]+temp.v*temp.p+temp.a1.v*temp.a1.p+temp.a2.v*temp.a2.p);
}
}
}
}
System.out.println(dp[m][len]);
}
}