ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

牛客网 华为 机试 HJ16 购物单

2022-02-19 12:34:41  阅读:272  来源: 互联网

标签:HJ16 int things price 牛客 thingsVec secondAppendix 物品 购物单


题目地址:https://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4?tpId=37&tqId=21239&rp=1&ru=/ta/huawei&qru=/ta/huawei&difficulty=&judgeStatus=&tags=/question-ranking

/*
一看就是背包问题,但是题目中对01背包进行了条件的添加,但主要思路不变,依旧尝试还原为简单的01背包问题。
具体实现思路是将附属物品看作是主物品的一种属性,将特殊的物品之间的关系还原为01背包是解题关键。
由题意可知,一个主物品可以不存在附属物品,或者有一个附属物平,或者有两个,因此可将背包的情况扩充。
主要分为4种情况:
  1、不放入;
  2、放入但不放入主物品的附属;
  3、放入且放入其中一个附属物品(放入哪个就要再分为两种情况考虑);
  4、放入且放入两个附属物品;
  这样就不需要考虑附属物品与主物品之间的关系,还原成熟悉的01背包问题了。
*/
#include<bits/stdc++.h>

using namespace std;
//存放物品信息的结构体
struct Thing{
  int price = 0;
  int importance = 0;
  int kind = 0;                 //此物品是主物品还是副物品
  Thing* firstAppendix = NULL;  //此主物品对应的第一个附属物品
  Thing* secondAppendix = NULL; //此主物品对应的第二个附属物品
};

int main(void){
  int money = 0;
  int count = 0;
  cin >> money;
  cin >> count;
  Thing things[count];//先把所有物品的信息存放在things中
  
  for(int i = 0;i < count;i++){
    cin >> things[i].price >> things[i].importance >> things[i].kind;
    things[i].price /= 10;//由于所有价格都是10的倍数因此可以先缩放10倍减少运算开销
  }
  
  vector<vector<int>> bag;//申请背包空间
  vector<int> wide(money / 10 + 1);//背包的“宽度”是依据输入的money所决定的,此基础上再添加一列代表了背包列初始状态
  bag.push_back(wide);//背包行初始状态
  //遍历找到所有附属物品并将其地址写入其主物品的相关属性中(firstAppendix和secondAppendix)
  for(int i = 0;i < count;i++){
    if(things[i].kind != 0){
      if(things[things[i].kind - 1].firstAppendix == NULL){  //注意两个附属物品肯定不重复,要进行条件判断
        things[things[i].kind - 1].firstAppendix = &things[i];
      }else{
        things[things[i].kind - 1].secondAppendix = &things[i];
      }
    }
  }
  
  vector<Thing> thingsVec;//thingsVec用来存放所有主物品
  
  Thing nullThing;
  thingsVec.push_back(nullThing);//初始化thingsVec时为了后续操作方便,将角标后移,以便于对应背包的角标
  //遍历things将主物品全部放入thingsVec
  for(int i = 0;i < count;i++){
    if(things[i].kind == 0){
      bag.push_back(wide);
      thingsVec.push_back(things[i]);
    }
  }
  //开始背包运算,注意是遍历thingsVec中的所有主物品,已经排除了附属物品
  for(int i = 1;i < bag.size();i++){
    for(int j = 1;j < wide.size();j++){
      //不放的情况
      int notPutIn = bag[i - 1][j];
      //放入但不放入其附属物品
      int putInWithoutAppendix =
        (j - thingsVec[i].price >= 0) ?
          bag[i - 1][j - thingsVec[i].price] + thingsVec[i].price * thingsVec[i].importance
        :0;
      //放入且放入第一个附属物品(对应附属物品存在并且放得下)
      int putInWithFirstAppendix =
        (thingsVec[i].firstAppendix != NULL) ?
          (j - thingsVec[i].price - thingsVec[i].firstAppendix->price >= 0) ?
            bag[i - 1][j - thingsVec[i].price - thingsVec[i].firstAppendix->price] + thingsVec[i].price * thingsVec[i].importance +
            thingsVec[i].firstAppendix->price * thingsVec[i].firstAppendix->importance
          :0
        :0;
      //放入且放入第二个附属物品(对应附属物品存在并且放得下)
      int putInWithSecondAppendix = (thingsVec[i].secondAppendix != NULL) ?
            (j - thingsVec[i].price - thingsVec[i].secondAppendix->price >= 0) ?
              bag[i - 1][j - thingsVec[i].price - thingsVec[i].secondAppendix->price] + thingsVec[i].price * thingsVec[i].importance + 
              thingsVec[i].secondAppendix->price * thingsVec[i].secondAppendix->importance
            :0
          :0;
      //放入且两个附属物品都放入(对应附属物品存在并且放得下)
      int putInWithTwoAppendix = (thingsVec[i].secondAppendix != NULL && thingsVec[i].secondAppendix != NULL) ?
            (j - thingsVec[i].price - thingsVec[i].firstAppendix->price - thingsVec[i].secondAppendix->price >= 0) ?
              bag[i - 1][j - thingsVec[i].price - thingsVec[i].firstAppendix->price - thingsVec[i].secondAppendix->price] + thingsVec[i].price * thingsVec[i].importance +
              thingsVec[i].firstAppendix->price * thingsVec[i].firstAppendix->importance +
              thingsVec[i].secondAppendix->price * thingsVec[i].secondAppendix->importance
            :0
          :0;
      bag[i][j] = max({notPutIn,putInWithoutAppendix,putInWithFirstAppendix,putInWithSecondAppendix,putInWithTwoAppendix});
    }
  }
  cout << (bag[bag.size() - 1][wide.size() - 1]) * 10;//由于之前对价格进行/10操作,因此背包中数据是实际数据的0.1倍,要在最后还原数据就要再乘以10
  return 0;
}

 

标签:HJ16,int,things,price,牛客,thingsVec,secondAppendix,物品,购物单
来源: https://www.cnblogs.com/Kisen-markDown/p/15912251.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有