3007 装箱问题

问题描述:

一个工厂生产的产品形状都是长方体,高度都是h,主要有1*1,2*2,3*3,4*4,5*5,6*6等6种。这些产品在邮寄时被包装在一个6*6*h的长方体包裹中。由于邮费很贵,工厂希望减小每个订单的包裹数量以增加他们的利润。因此他们需要一个好的程序帮他们解决这个问题。你的任务就是设计这个程序。

输入:

输入包括多组测试数据,每一行代表一个订单。每个订单里的一行包括六个整数,用空格隔开,从小到大分别为这6种产品的数量。6个0表示文件结束。

输出要求:

针对每个订单输出一个整数,占一行,代表对应的订单所需的最小包裹数。没有多余的空行。

输入样例:

0 0 4 0 0 1

7 5 1 0 0 0

0 0 0 0 0 0

输出样例:

2

1

 

解题分析:

6*6:毫无疑问,6*6的产品每个都会占用一整个箱子,因此有多少个6*6的产品,必须有多少个箱子,而且没有任何空余的空间存放其他产品

5*5:该产品也必须自己占用一个箱子,但是会有剩余,剩余的部分为6*6-5*5=11,这11个空间很显然只能存放1*1大小的产品,因此,5*5的可以和1*1放在一起,可以放11个1*1的产品

4*4:该产品也需要自己占用一个箱子,剩余的空间既可以放5个2*2的产品,也可以放20个1*1的产品


3*34个3*3的产品正好可以装满一个整箱子。如果3*3的产品数来对4求余的余数为0直接除以4就是所需的箱子数,不再有剩余空间

如果余数不为0,那么则是除以4取整后再加1,这时候就会出现剩余空间

如果余数为1,1个箱子里只放1个3*3的产品,那么剩余的空间为27最多可以放5个2*2的箱子和7个1*1的箱子。

如果余数为2,剩余的空间为18最多可以放3个2*2的箱子和6个1*1的箱子

如果余数为3,则剩余空间为9最多只能放1个2*2和5个1*1

(注:这里考虑剩余空间,紧着比较大的箱子去放,也就是紧着2*2的箱子放,所以没有写空隙全部放1*1小箱子的情况)


2*2可以和4*4或3*3产品放一起,如果空隙占满了箱子还没放完,则需要占用新箱子,9个2*2产品正好占满一个箱子,所需新箱子的数量应该对9求余,余数为0,则直接整除9即可,否则整除9后再加1。

1*1:与2*2类似,先把所有剩余的1*1空间占满,如果不够,则重新占用新箱子,一个箱子可以存放36个1*1,因此剩余的1*1产品数对36求余,余数为0,直接整除36,否则整除36加1。

最后把这6种情况各自所需的箱子数累加起来就是题目所要的结果。

代码(主要是从最大的箱子开始分析,小箱子就是插空用的,最后再考虑小箱子的剩余情况)(贪心算法)icon-default.png?t=M276https://zhuanlan.zhihu.com/p/53334049

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
	int a,b,c,d,e,f;
	while(1){
		scanf("%d %d %d %d %d %d",&a,&b,&c,&d,&e,&f);
		if(a==0&&b==0&c==0&d==0&e==0&f==0) break;
		int i=f;//6*6的箱子单独占一个
		int t;//用于存放放3*3箱子后还能装多少2*2箱子的变量
		if(e>0){
			i+=e;//5*5的箱子单独占一个
			a-=(11*e);//5*5其余空隙放1*1箱子后剩下的1*1箱子数量
		}
		if(d>0){
			i+=d;//4*4的箱子单独占一个
			b-=(5*d);//4*4其余空隙全部放2*2箱子后剩下的2*2箱子数量
			if(b<=0){//2*2箱子放完了还有空隙,就放1*1的
				a-=(d*16)-b*4;//剩下空间都放1*1箱子之后1*1箱子的剩余数量
				b=0;
			}
			else{//2*2箱子放完后没有空隙
				b-=(d*5);
			}
		}
		if(c>0){//放3*3箱子
			i+=(c/4);//一个大箱子装4个3*3箱子
			c%=4;
			if(c){//3*3箱子放不满大箱子,余数有3,2,1三种情况
				i++;
				t=(4-c)*2-1;//放c个3*3的箱子后还能放下t个2*2的箱子 
				if(b>t){//2*2箱子放空隙没放下 
					b-=t;//剩余的2*2箱子
					a-=(36-9*c-4*t);//剩余空隙放1*1
				}
				else{//2*2箱子全部能放空隙里
					b=0;
					a-=(36-9*c-4*b);//剩余空间放1*1
				}
			}
		}
		if(b>0){//放剩下的2*2箱子
			i+=(b/9);//一个大箱子放9个2*2箱子
			if(b%9){//一个箱子全放2*2之后还剩有2*2的箱子 
				i++;
				a-=(36-((b%9)*4));//剩余空隙放1*1箱子
			}
		}
		if(a>0){
			i+=(a/36);//一个大箱子放36个1*1箱子
			if(a%36) i++;
		}
		printf("%d\n",i);
	} 
	return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值