题解 | #购物单#

import java.util.Scanner;
/*

  • 物品分为主副件,每个主件可能有附件(最多有两个附件),买要买附件则必须买起对应的主件,求在资金一定的情况下能够买到的最大贡献度

  • 贡献度=价值*重要程度

  • 物品goods:

  • p:表示物品价值 w:表示贡献度 q:表示该物品是否为主件,若为则q=0,若不为则q表示所对应的主件序号

  • dp[m][n]:表示在资金为m的情况下从n个物品中能够买到的最大贡献度

  • dp[m][n] = max{不买第n个物品,买第n个物品}

  • 当第n个物品为附件时,此时是不能购买该物品的

  • dp[m][n] = dp[m][n-1];

  • 当第n个物品不为附件时,此时购买该物品时可以购买该物品的附件,因此最多可以分为4种情况

  • 情况1:只买主件 情况2:买主件+附件1 情况3:买主件+附件2 情况3:买主件+附件1+附件2

  • 情况1:只买主件 = dp[m-goods.p][n-1]+goods.p*goods.w

  • 情况2:买主件+附件1 = dp[m-goods.p-goods.附件1.p][n-1] + goods.pgoods.w + goods.附件1.pgoods.附件1.w

  • 情况3:买主件+附件1 = dp[m-goods.p-goods.附件2.p][n-1] + goods.pgoods.w + goods.附件2.pgoods.附件2.w

  • 情况4:买主件+附件1 = dp[m-goods.p-goods.附件1.p-goods.附件2.p][n-1] +

  • goods.pgoods.w + goods.附件1.pgoods.附件1.w +

  • goods.附件2.p*goods.附件2.w

  • dp[m][n] = max{不买第n个物品,买第n个物品} = max{dp[m][n-1],情况1,情况2,情况3,情况4};

  • /
    public class Main {
    public static void main(String[] args) {

      Scanner sc = new Scanner(System.in);
      //输入资金
      int m = sc.nextInt();
      //输入物品总数
      int n = sc.nextInt();
      //输入物品信息
      goods[] goods = new goods[n+1];
      for (int i = 1; i <= n; i++) {
          int p = sc.nextInt();
          int w = sc.nextInt();
          int q = sc.nextInt();
          //构造商品
          goods[i] = new goods(p, w, q);
          if (q!=0) {//表明第i个物品是第q个物品的附属品
              if (goods[q].add1==0) {
                  goods[q].add1 = i;
              }else{
                  goods[q].add2 = i;
              }
          }
      }
      System.out.println(calue(m,n,goods));

    }

    private static int calue(int m, int n, goods[] goods) {

      int[][] dp = new int[m+1][n+1];
      for (int i = 1; i <= m; i++) {//表示金钱
          for (int j = 1; j <= n ; j++) {//表示物品
              //判断第j件物品是否为主件
              if (goods[j].q==0) {//为主件
                  int p1 = 0,p2 = 0,p3 = 0,p4 = 0;
                  int v1 = 0,v2 = 0,v3 = 0,v4 = 0;
                  //情况1:只买主件
                  p1 = goods[j].p; //价格
                  v1 = goods[j].p*goods[j].w; //贡献
                  //情况2:买主件+附件1
                  if (goods[j].add1!=0) {
                      p2 = goods[j].p + goods[goods[j].add1].p;
                      v2 = goods[j].p*goods[j].w + goods[goods[j].add1].p*goods[goods[j].add1].w;
                  }
                  //情况3:买主件+附件2
                  if (goods[j].add2!=0) {
                      p3 = goods[j].p + goods[goods[j].add2].p;
                      v3 = goods[j].p*goods[j].w + goods[goods[j].add2].p*goods[goods[j].add2].w;
                  }
                  //情况4:买主件+附件1+附件2
                  if (goods[j].add1!=0 && goods[j].add2!=0) {
                      p4 = p2+p3-p1;
                      v4 = v2+v3-v1;
                  }
                  dp[i][j] = dp[i][j-1];
                  if (p1<=i) {
                      dp[i][j] = Math.max(dp[i][j], dp[i-p1][j-1]+v1);
                  }
                  if(p2<=i && p2!=0){
                      dp[i][j] = Math.max(dp[i][j], dp[i-p2][j-1]+v2);
                  }
                  if(p3<=i && p3!=0){
                      dp[i][j] = Math.max(dp[i][j], dp[i-p3][j-1]+v3);
                  }
                  if(p4<=i && p4!=0){
                      dp[i][j] = Math.max(dp[i][j], dp[i-p4][j-1]+v4);
                  }
              }else{//为附件
                  dp[i][j] = dp[i][j-1];
              }
          }
      }
      return dp[m][n];

    }
    }
    class goods{
    int p;
    int w;
    int q;
    int add1 = 0;//表示附件1的序号
    int add2 = 0;//表示附件2的序号
    public goods(int p, int w, int q) {

      this.p = p;
      this.w = w;
      this.q = q;

    }
    }

全部评论

相关推荐

01-07 15:50
四川大学 Java
看日出看日落:好好背八股,做算法。我身边跟你bg差不多的基本都大厂暑期
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务