算法训练 装箱问题
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)。
要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
输入格式
第一行为一个整数,表示箱子容量;
第二行为一个整数,表示有n个物品;
接下来n行,每行一个整数表示这n个物品的各自体积。
输出格式
一个整数,表示箱子剩余空间。
样例输入
24
6
8
3
12
7
9
7
样例输出
0
思路与解析:
1、虽然题干提示这是一道动态规划,但显然这是一道比较简单基础的贪心,首先我们考虑这道题时要分析到如何能让剩余的空间最小,那么你就会想到尽可能装大的物品,装的大,才是最贪的,剩下的空间一定会很小,那我们初期思路就可以时先把物品的重量排序:(STL真好用)
#include<algorithm>
sort(&a[0],&a[n]);
2、比如说我们这时容量为10,4个物品,分别为2,3,1,4,那么sort之后数组就变成了1 2 3 4,然后我们可以从后(n-1)往前(0)开始遍历,满足条件如果物品小于容量,那么容量就减去物品大小:
for(int i =n - 1 ;i >= 0;i--)
{
if(box >= a[i])
{
box -= a[i];
}
}
※正当我兴高采烈的提交代码时,样例却只给了我80分(不得不说数据真的很水,要不然40都得不到)
这时开始思考有没有特殊的情况没有考虑到?
比如:容量为10 , 5个物品,分别为1 2 3 4 5,那么如果从后往前看的话,先装5,再装4,就已经不能再装了,剩余空间为1,但是我们肉眼能判断 1 + 2 + 3 + 4 == 10,应该装法是 4 3 2 1才对,那么这时思路就要改变,算法要从O(n)变成O(n²),因为第一个装的物品不同的情况下,最后剩余的空间也不同,那么就要遍历每一种情况开头时候他的剩余空间,然后取这些剩余空间的最小值就好啦!
int ans = box; //答案最初等于箱子的容量
for(int i =n - 1 ;i >= 0;i--) //i是第一个装的物品
{
min_val = box; //每一次最小值要重置为箱子初始的容量
for(int j = i ;j>= 0;j-- ) //第一个是i的情况下,向前遍历
{
if(min_val >= a[j]) //如果容量比物品大,那就装!
{
min_val -= a[j]; //减去物品
}
}
ans = min(ans,min_val); //在答案和每次剩余容量中取最小值
}
3、本题可能用到了dp,但是我暂时还没有去想,大家可以看看其他大佬的代码和思路
最后附上完整AC代码:
#include <stdio.h>
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
int box,n,min_val;
int a[32]; ///装物品
cin >> box >> n;
int ans = box;
for(int i = 0;i < n; i++)
{
cin >> a[i];
}
sort(&a[0],&a[n]);
for(int i =n - 1 ;i >= 0;i--)
{
min_val = box;
for(int j = i ;j>= 0;j-- )
{
if(min_val >= a[j])
{
min_val -= a[j];
}
}
ans = min(ans,min_val);
}
cout << ans;
return 0;
}