完美世界2016实习生招聘编程题-小萌的包裹

来源:互联网 发布:it行业是什么意思 编辑:程序博客网 时间:2024/05/01 01:46

最近在牛客网上刷题,其中完美世界的实习生招聘的一道编程题觉得很有意思,就贴出来和大家分享!!!题目是这样的:



看到这个题想到的是贪心算法,但是后来想想觉得不对(在贪心算法中,物品放入背包的顺序不是物品的排列顺序,而是按照一定的条件进行,比如按价值量/体积的商的大小装入,使得背包的总价值量最大等等)。但是这个题主要有以下特点:

(1).一旦不往一个包里放物品,这个背包的口将封住不再使用。假设有小萌有两个背包,编号为1和2。一旦小萌决定往第2号背包里放东西的时候,第1号背包即再也不能放进任何物品,也就是说,背包是按顺序放进物品,先1后2。

(2)物品的处理也是按顺序的,从第1号物品开始到最后一个物品,每个物品只有两个情况,要么放进当前正在装物品的背包,要么放弃装入。装入的过程也是从1号背包开始一直到第n号背包。

在以上的前提下,有人提出了动态规划的方法来解题,如http://www.cnblogs.com/wen-ge/p/5442095.html.本文将利用树形结构来解决!

思路如下:

假设有如下测试用例

3 2 2

1 2 1 

那么我们将会有以下的访问树:


数中的每一个节点都有自己专属的四个变量:(1).目前已经用了多少个袋子packets_used;(2)目前正在处理物品的编号index;(3)当前袋子的剩余容量;(4)目前已经装入袋中的物品的个数;这四个变量可以保证每一个物品应该如何装入哪一个袋子中。当袋子已经用尽时,停止处理。

那么对于1,2,1这三个物品中的每一个,按照数的深度遍历来处理对应的包裹是否加入到背包中,以上图的A,B两个状态为例。在状态A中,数的路径是001(表示第1,第2号物品不装入背包,到第3个物品才装入第1个背包),那么背包使用个数是1,物品装入的个数是1;同样的对于B状态的树的访问路径是111,则表示理论上(说是理论上,其实要考虑背包的个数,以及是否要重新启用一个新的背包)三个物品全部加入到背包中,但是由于在装入第1个物品之后,背包1剩下的体积无法再装入第二个物品,所以此时必须要启用一个新的背包,所以此时只能将第1号背包封住,启用第二号背包来装第2号物品,装入2号物品后背包2的剩余体积为0,不能装入第3号物品(这就是剪枝操作,经过剪枝操作之后的树的访问深度会大大减少,从而减少算法时间).

以下是代码部分:

#include<iostream>#include<vector>#include<list>#include<fstream>#include<string>#include<unordered_set>#include<map>#include<algorithm>#include<stack>using namespace std;class solution{public:void TheBiggestNumberOfGifts(int packets_used,int index,int leftv,int load){//index表示当前正在处理的物品下标if (index>gifts-1)return;if (data[index]<=leftv){//加入的情况不需要从新启用一个袋子if (load+1 > re)re = load+1;TheBiggestNumberOfGifts(packets_used,index+1,leftv-data[index],load+1);}else{//加入需要重新使用一个袋子if (packets_used + 1 <= number){//物品的最大体积必须不大于袋子的体积if(data[index]>volume)TheBiggestNumberOfGifts(packets_used+1, index + 1, volume, load);else {if (load+1 > re)re = load+1;TheBiggestNumberOfGifts(packets_used+1, index + 1, volume - data[index], load+1);}}}//不加入TheBiggestNumberOfGifts(packets_used,index+1,leftv,load);}vector<int>data;int gifts;//物品的总个数int volume;//每个袋子的体积int number;//袋子的总个数int re;//目前最大的物品装载数};int main(){//ifstream fin("C:\\Users\\caoyan\\Desktop\\data.txt");string str;int num,temp;vector<int>data;solution aa;cin >> num;while (num){cin >> aa.gifts >> aa.volume >> aa.number;aa.data.clear();for (int i = 0; i < aa.gifts;i++){cin >> temp;aa.data.push_back(temp);}aa.re = 0;aa.TheBiggestNumberOfGifts(1, 0, aa.volume, 0);cout <<aa.re<< endl;////分别代表已经用了多少个袋子,物品装载的起始下标,当前袋子的剩余容量,目前已装载物品的个数num--;}}
然而得到的测试结果是:

在下就不懂了,为什么可以容量为11的背包可以装得下大于体积为11的物品,测试用例的设计人员你出来解释一下!!!!!

以下是我自己的测试数据是没问题的!!!!!数据如下:


测试结果:


0 0
原创粉丝点击