神犇营-my1051-装箱问题

版权声明:本文为博主原创文章,未经博主允许不得转载。如需转载,请与博主联系。 https://blog.csdn.net/qq_31790997/article/details/88910909

【小韦同学@神犇营-my1051-装箱问题】

题目:

描述

有一个箱子容量为 V(正整数,0 ≤ V ≤ 20000),同时有 n 个物品(0< n ≤ 30),每个物品有一个体积(正整数)。
要求 n 个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

输入

1个整数,表示箱子容量
1个整数,表示有 n 个物品
接下来 n 行,分别表示这 n 个物品的各自体积

输出

1个整数,表示箱子剩余空间。

输入样例1

24
6
8
3
12
7
9
7

输出样例1

0

题解:

/********************************************************************* 

* 题目:神犇营-my1051-装箱问题 
* 作者:小韦同学 
* 邮箱:[email protected] 

* 题解:
	思路:
	从n个物体中任意选一些物体放入背包,要求背包可能的最小剩余空间。
	我们需要考虑所有可能的物体选择组合,同时要求这个组合的总体积小于背包
	的容积。然后对每种组合,计算对应的背包剩余空间,选择最小的。 
	我们可以从第1个物体开始,依次选择每个物体是否放入背包。
	在做选择前,我们首先要考虑背包里是否还能放下这个物体,如果已经放不下了,
	那我们没有选择的余地,只能不放;如果还能放下,我们可以选择放,也可以选择不放。
	举个例子:物体的体积依次为3 6 5 ,背包容量为10
	先考虑第一个物体 体积为3 此时背包容量为10 能放下
	我们可以选择放入,则此时背包容量为10-3=7
	也可以选择不放入,此时背包容量仍为10
	在考虑完第一个物体后,这个问题会产生两个新的问题:
	选择放入第一个后:剩下的物体体积为 6 5, 背包容量为7
	选择不放入第一个后:剩下的物体体积为 6 5, 背包容量为10
	不难看出,产生的新问题和最初的问题其实是类似的,具有相同的结构。
	因此可以考虑递归的思想来解决这个问题。
	形式化的定义这个问题:
	物体1-n的体积为a1、a2...an,背包体积为V 
	我们只需要递归的考虑每个物体,直到第n个为止,看看背包剩余容积为多少
	我们首先令最小的剩余体积R=V 
	对于第i个物体,假设此时的背包剩余体积为R,那么:
	我们有两种选择: 
		放入i(前提是ai<R),背包剩余容积R=R-ai 
		不放入i,背包剩余容积R=R-0
	此外,我们还需要为递归增加终止条件,即判断什么时候,递归结束。
	根据问题可知,如果考虑所有n个物体,则需要结束。 
	注意:
	
*********************************************************************/ 
#include<bits/stdc++.h>
using namespace std;

const int MAX = 50;
int items[MAX];
bool judge[MAX];
int min_v = 2e4 + 10;  // 用来记录箱子最小剩余空间 

// 参数:枚举物品的下标,箱子剩余空间,箱子容量,物品个数 
void put_items(int idx, int remain, int v, int n){
	// 如果箱子剩余空间小于0 
	if(remain < 0) return;
	if(remain < min_v){  // 若箱子剩余空间小于min_v 
		min_v = remain;  // 更新箱子最小剩余空间 
	}
	// 枚举每一个物品 
	for(int i = idx; i < n; i++){
		if(!judge[i]){  // 若当前物品未装箱 
			judge[i] = true;  // 表示标记该物品已装箱 
			// 递归调用函数 
			put_items(i+1, remain-items[i], v, n);
			judge[i] = false;  // 将该物品标记为未装箱 
		}
	}
}

int main(){
	int v, n;
	cin >> v >> n;
	for(int i = 0; i < n; i++) {
		cin >> items[i];
		judge[i] = false; // 表示物品未被装入 
	}
	// 将物品体积升序排列 
	sort(items, items + n);  
	put_items(0, v, v, n);
	cout << min_v;
	
	return 0;
}   

我是小韦同学,企者不立,跨者不行,每天进步一点点。
欢迎大家多多交流,如果发现有错误,请多指正。有疑问的同学也可以留言评论或者发邮件。
邮箱:[email protected]

猜你喜欢

转载自blog.csdn.net/qq_31790997/article/details/88910909