题解 | #购物单#
购物单
https://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4
import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int budget = in.nextInt(); int quantity = in.nextInt(); Item[] items = new Item[quantity]; for(int i = 0; i < quantity; i++){ items[i] = new Item(); } int maxSatisfy = 0; for (int i = 0; i < quantity; i++) { int price = in.nextInt(); int important = in.nextInt(); int parent = in.nextInt(); items[i].important = important; items[i].price = price; items[i].parent = parent; if (parent != 0) { if (items[parent-1].sub1 == -1) { items[parent-1].sub1 = i; } else { items[parent-1].sub2 = i; } } } int[][] qb = new int[quantity+1][budget+1]; for (int i = 1; i <= quantity; i++) { int satisfyMainSub1 = 0, satisfyMainSub2 = 0, satisfyMainSub1Sub2 = 0; int priceMain = 0, priceMainSub1 = 0, priceMainSub2 = 0, priceMainSub1Sub2 = 0; Item item = items[i-1]; // only main int satsfyMain = item.getSatisfy(); priceMain = item.price; if (item.sub1 >= 0) { // main + sub1 priceMainSub1 = priceMain + items[item.sub1].price; satisfyMainSub1 = satsfyMain + items[item.sub1].getSatisfy(); } if (item.sub2 >= 0) { // main + sub2 priceMainSub2 = priceMain + items[item.sub2].price; satisfyMainSub2 = satsfyMain + items[item.sub2].getSatisfy(); } // main + sub1 + sub2 if (item.sub1 >= 0 && item.sub2 >= 0) { priceMainSub1Sub2 = priceMain + items[item.sub1].price + items[item.sub2].price; satisfyMainSub1Sub2 = satsfyMain + items[item.sub1].getSatisfy() + items[item.sub2].getSatisfy(); } for (int j = 0; j <= budget; j++) { if (item.parent == 0) { qb[i][j] = qb[i-1][j]; if(j>=priceMain) qb[i][j] = Math.max(qb[i][j], qb[i-1][j - priceMain]+satsfyMain); if(j>=priceMainSub1&&item.sub1 >= 0) qb[i][j] = Math.max(qb[i][j], qb[i-1][j - priceMainSub1]+satisfyMainSub1); if(j>=priceMainSub2&&item.sub2 >= 0) qb[i][j] = Math.max(qb[i][j], qb[i-1][j - priceMainSub2]+satisfyMainSub2); if(j>=priceMainSub1Sub2&&item.sub1 >= 0 && item.sub2 >= 0) qb[i][j] = Math.max(qb[i][j], qb[i-1][j - priceMainSub1Sub2]+satisfyMainSub1Sub2); } else { qb[i][j] = qb[i-1][j]; } } } System.out.println(qb[quantity][budget]); } } class Item { int important; int price; int parent; int sub1=-1;// sub1 index int sub2=-1;// sub2 index(other item parent-1) public int getSatisfy() { return important * price; } }
借鉴了别人的, 动态算法, 妙啊
如用例
1000 5
300 5 0
400 2 0
300 5 2
300 4 2
600 4 0
0 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 | |
300 - 5 -0 | 0 | 0 | 0 | 1500 | 1500 | 1500 | 1500 | 1500 | 1500 | 1500 | 1500 |
400 -2 -0 [300-5-2] [300-4-2] | 0 | 0 | 0 | 1500 | 1500 | 1500 | 1500 | 2300 | 2300 | 2300 | 3500 |
600-4-0 | 0 | 0 | 0 | 1500 | 1500 | 1500 | 2400 | 2400 | 2400 | 3900 | 3900 |
当计算完物品1价值后: 得到的最大满意度是物品1的最大满意度
当计算完物品1,物品2(由于物品2 有两个子类,需要同时计算)后: 得到的最大满意度是对应价值能购买到的物品的最大满意度之和。所以到价值是600时,由于其购买到的物品2价值=800,相比若购买物品1价值=1500满意度低,所以取满意度最大值1500。 但是当价值为700时,其可购买物品2+物品2子类1达到满意度2300,故当700 时, 满意度=2300. 其对应的公式为
首先设置dp[2][700] = dp[1][700]
dp[2][700] = Math.max(dp[2][700],dp[2][1000-700] + 物品2满意度) = Math.max(1500, 1500+800) = 2300
物品2满意度的可能性有4种, 物品2, 物品2+子类1, 物品2+子类2,物品2+子类1+子类2; 记录对应的钱数,当钱数小于总价格时, 可以通过比较拿到对应位置的最大满意度。
计算完物品3同理。