【题目大意】
有6种规格的物品,分别是$6*6,5*5,4*4,3*3,2*2,1*1$,高度均为$H$,先有一种高为$H$,规格为$6*6$的包裹可以装物品,求最少需要多少个包裹可以装下所有物品。
【思路分析】
分类讨论一下:
1.$6*6$的物品每个都要一个包裹
2.$5*5,4*4$的物品每个包裹也只能装一个,但要记录余下的空间可以存放几个$1*1$和$2*2$的物品
3.$3*3$的物品每个包裹可以装4个,对于每个箱子里装了不同个$3*3$的物品的情况,可以存放不同个数$2*2$的物品,也要记录
4.先把前面所有可以放$2*2$的物品的位置装完,然后如果有剩余,再另开箱子
5.先把前面所有的空余位置装完,然后如果有剩余,另开箱子存放$1*1$的物品
很多细节部分要注意,详见代码。
【代码实现】
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define g() getchar() 7 #define rg register 8 #define go(i,a,b) for(rg int i=a;i<=b;i++) 9 #define back(i,a,b) for(rg int i=a;i>=b;i--) 10 #define db double 11 #define ll long long 12 #define il inline 13 #define pf printf 14 using namespace std; 15 int fr(){ 16 int w=0,q=1; 17 char ch=g(); 18 while(ch<'0'||ch>'9'){ 19 if(ch=='-') q=-1; 20 ch=g(); 21 } 22 while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=g(); 23 return w*q; 24 } 25 int num[7],a1=0,a2=0,ans=0,tag[4]={0,5,3,1}; 26 //tag记录的是放了i个3*3的物品之后,还能放多少个2*2的 27 int main(){ 28 //freopen("","r",stdin); 29 //freopen("","w",stdout); 30 rg int end=0; 31 while(1){ 32 a1=0;a2=0;ans=0;end=0; 33 go(i,1,6){ 34 num[i]=fr(); 35 end+=num[i]; 36 } 37 if(!end) break; 38 back(i,6,1){ 39 if(!num[i]) continue; 40 if(i==6) {ans+=num[i];continue;} 41 if(i==5) {ans+=num[i];a1+=11*num[i];continue;}//a1记录可以放多少个1*1的物品 42 if(i==4) {ans+=num[i];a2+=5*num[i];continue;}//a2记录可以放多少个2*2的物品 43 if(i==3){ 44 rg int add=ceil(1.0*num[i]/4);ans+=add; 45 if(add*4>num[i]){ 46 rg int a2_add=tag[num[i]%4]; 47 a2+=a2_add; 48 a1+=(add*4-num[i])*9-a2_add*4; 49 } 50 } 51 if(i==2){ 52 if(num[i]<a2) {a2-=num[i];continue;} 53 num[i]-=a2;a2=0; 54 rg int add=ceil(1.0*num[i]/9);ans+=add; 55 if(add*9>num[i]) a1+=(add*9-num[i])*4; 56 } 57 if(i==1){ 58 a1+=a2*4; 59 if(num[i]<a1) {continue;} 60 num[i]-=a1; 61 rg int add=ceil(1.0*num[i]/36);ans+=add; 62 } 63 } 64 pf("%d ",ans); 65 } 66 return 0; 67 }