1014 装箱问题——http://codevs.cn/problem/1014/
第一部分:题目
题目描述 Description
有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)。
要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
输入描述 Input Description
一个整数v,表示箱子容量
一个整数n,表示有n个物品
接下来n个整数,分别表示这n 个物品的各自体积
输出描述 Output Description
一个整数,表示箱子剩余空间。
样例输入 Sample Input
24
6
8
3
12
7
9
7
样例输出 Sample Output
0
第二部分:思路
开始以为只要把数从小到大排列然后从大的开始装一直到不能装为止就能得到结果。然后就WA了。比如10 4 3 5 4 8.结果应该是1,但是这样的想法得出的是2.然后就想到了动态规划(虽然题目写的就是动态规划类,本想偷点懒。。。)就是使用递归慢慢装,然后判断,结果TLE(超时)了。然后发现:直接递归的话,重复了好多操作,比如10 4 3 5 4 8.先把3 5 4 8按从大到小排序:3 4 5 8.就会重复计算8 +5、5+8.当数比较多的时候就会超时。这里需要添加一个细节:从当前数开始继续加后面的数。就可以避免重复计算了。然后就AC了。
第三部分:代码
#include<stdio.h> int sum=0,take[30],length=0,max=0;//take 数组用来存储已经装进包里的数的位置。避免重复添加 void paixu(int s[30],int len)//从大到小排序 { int i,j,t; for(i=0;i<len;i++) { for(j=i+1;j<len;j++) { if(s[i]<s[j]) { t=s[i]; s[i]=s[j]; s[j]=t; } } } } void compute(int s[30],int len,int v,int index)//进行装包 { int i; for(i=index;i<len;i++) { int j; for(j=0;j<length;j++) { if(i==take[j]) { break; } } if(j==length&&sum+s[i]<=v)//判断是否能够装进去,即剩余空间是否足够容纳当前物品 { sum+=s[i]; take[length++]=i; if(max<sum)//记录所有可能装发中体积最大值 { max=sum; } if(sum<v)//还有剩余控件继续往后加 ,避免超时 { compute(s,len,v,i+1); } length--;//当前装发结束,继续下一次前先清除上一次操作 sum-=s[i]; } } } int main() { int v,n,i,s[30]; scanf("%d%d",&v,&n); for(i=0;i<n;i++) { scanf("%d",&s[i]); } paixu(s,n); int sum=0; compute(s,n,v,0); printf("%d\n",v-max);//打印剩余空间 return 0; }
害怕失败的人,已经是一个loser!