这周的问题终于有些难度了,终于不是一眼看过去就有能写出大概的题目了,还有就是,我又找不到题目了,所以去网上扒了一下,英语的:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 28329 | Accepted: 9291 |
Description
Input
Output
Sample Input
0 0 4 0 0 1
7 5 1 0 0 0
0 0 0 0 0 0
Sample Output
2
1
看完题我第一反应就是贪心,用最少的箱子装最多的货物。确定了贪心之后便开始思考,如何解题。首先每一新箱子都有 6*6 = 36 的空间,然后看货物,细细一想,发现 边长大于3的货物都需要单独开一个箱子,所以便有了第一行代码
sum += goods4 + goods5 + goods6;
又反复的思考了一下3的情况 一个 6*6的箱子能够装4个3*3的箱子。所以上面的算法就可以修改成
sum += goods4 + goods5 + goods6 + ((goods3 - 1) / 4 + 1);//向上取整,多出来的一个必须多开一个箱子
为什么多出来的3*3货物必须多开一个箱子呢,分析一下空间就可以了,题目中说物品高度相同,所以只需要考虑占地面积,5*5 和 4*4 的货物所占的盒子虽然还有空间,但是它们余下的空间只能够存放1*1或者2*2的货物,所以多出来的3*3必须额外开辟一个空间。到了这一步问题就来了,3*3的货物是4的倍数那最好,如果3*3的货物不是4的倍数,那么就必须额外开一个箱子,用来存放余下的3*3的货物,那么存放多余的的组成不成一件3*3的货物肯定会有多余空间,而且余数不止一种,我们就需要进行分类讨论。嗯好,我们来继续分析,现在3*3的货物是被全部放下了,但是由于3*3的货物不是 4 的倍数, 难么肯定就会有多余的空间,而且根据余数的不同肯定有不同的情况。那么余数有几种可能呢 ?唔,让我们来想一想,一个 箱子可以放4个3*3,那么x%4的可能只有4种吧,0、1、2、3 。
现在我们来分析一下 3*3 的情况,无剩余的情况就不分析了
画个图就可以直观的看到结果了:
由图可知:
![](https://i-blog.csdnimg.cn/blog_migrate/0cf38aefe6090b4cb93a6bf5f435a4a5.png)
1、当余下1个的时候还能装7个1*1和5个2*2,
2、当余下2个的时候还能装6个1*1和3个2*2,
2、当余下3个的时候还能装5个1*1和1个2*2,
得出相应的代码:
if (goods3 % 4 == 1)
{
spaceby1 += 7;
spaceby2 += 5;
} //余下1个3*3所余下的1*1和2*2的空间
if (goods3 % 4 == 2)
{
spaceby1 += 6;
spaceby2 += 3;
} //余下2个3*3所余下的1*1和2*2的空间
if (goods3 % 4 == 3)
{
spaceby1 += 5;
spaceby2 += 1;
} //余下3个3*3所余下的1*1和2*2的空间
处理完3*3的就简单了,我们按顺序去处理2*2的货物. 在这之前们需要求出有多少地方可以存储2*2的货物,5*5是无法存储2*2 的货物的,但是4*4的可以4*4的里面还可以存放5个2*2 所以我们需要加上goods2
4*5。好了2*2的空间算完,那还得分类论。
很显然分为3总情况:
1、刚好存下,皆大欢喜
2、存不下,还得开空间
3、有剩余,计算剩余空间
让2*2的空间数与货物数进行比较够的话,就不用额外开空间了不够的话直接开空间
代码如下:
spaceby2 += 5 * goods4; //装一个4*4的时候余下的1*1和2*2的空间
if (spaceby2 < goods2) //2*2的空间小于2*2的盒子
{
//额外的2*2空间需要的箱子
sum += ((goods2 - spaceby2 - 1) / 9 + 1);
}
余下1*1 的模仿2*2的流程即可,1*1剩余空间建议用总箱子数*36 - 被占用的空间这样就可以快速的得出1*1的空间而且不容易错,(2*2不用这个方法是因为5*5的碎片空间虽然足够但是呢,它边长就……6*6,放不下2*2)1*1的就不单独贴代码了
下面贴一下完整的代码(能自己写出来的先自己写一遍),记得分析数据大小:
#include <stdio.h>
/**
* @author 杨文蓁的小迷弟
* @note 算法作业3
* @date 2019/09/05
*/
int main()
{
//北大OJ数据超过了正常的int,估计有一个50000的数据
unsigned int goods1, goods2, goods3, goods4, goods5, goods6; //1,2,3,4,5,6
while (scanf("%d %d %d %d %d %d", &goods1, &goods2, &goods3, &goods4, &goods5, &goods6) != EOF)
{
unsigned int sum = 0, spaceby1 = 0, spaceby2 = 0; //sum总箱子数,n余下放1x1的位置,m余下放2x2的位置
if (goods1 == 0 && goods2 == 0 && goods3 == 0 && goods4 == 0 && goods5 == 0 && goods6 == 0)
{
return 0;
}
sum += goods4 + goods5 + goods6 + ((goods3 +3) / 4); //最少需要开的箱子
if (goods3 % 4 == 1)
{
spaceby1 += 7;
spaceby2 += 5;
} //余下1个3*3所余下的1*1和2*2的空间
if (goods3 % 4 == 2)
{
spaceby1 += 6;
spaceby2 += 3;
} //余下2个3*3所余下的1*1和2*2的空间
if (goods3 % 4 == 3)
{
spaceby1 += 5;
spaceby2 += 1;
} //余下3个3*3所余下的1*1和2*2的空间
spaceby2 += 5 * goods4; //装一个4*4的时候余下的1*1和2*2的空间
if (spaceby2 <= goods2) //2*2的空间小于2*2的盒子
{
//额外的2*2空间需要的箱子
sum += ((goods2 - spaceby2 + 8) / 9);
}
//余下了多少 1*1 的空间
spaceby1 = 36 * sum - 36*goods6 - 25*goods5 - 16*goods4 - 9*goods3 - 4*goods2;
if (spaceby1 <= goods1)
{
sum += ((goods1 - spaceby1 + 35) / 36);
}
printf("%d\n", sum);
}
return 0;
}
贴个python的代码:
#author: 杨文蓁的小迷弟
#date: 2019/9/5
while (1):
s=input().split()
box_sum = spaceby1 = spaceby2 = 0
flag = True
for i in range(len(s)):
if int(s[i]) != 0:
flag = False
if flag == True:
exit()
box_sum = int(s[5]) + int(s[4]) + int(s[3]) + (int(s[2])-1) // 4+1
if int(s[2])%4 == 1:
spaceby1 += 5
spaceby2 += 7
if int(s[2])%4 == 2:
spaceby1 += 6
spaceby2 += 3
if int(s[2])%4 == 3:
spaceby1 += 5
spaceby2 += 1
spaceby2 += 5 * int(s[3])
if spaceby2 <= int(s[1]):
box_sum += ((int(s[1])-spaceby2-1)//9 + 1)
spaceby1 = 36*box_sum - 36*int(s[5]) - 25*int(s[4]) - 16*int(s[3]) - 9*int(s[2]) - 4*int(s[1]);
if spaceby1 <= int(s[0]):
box_sum += ((int(s[0])-spaceby1-1)//36 + 1)
print(box_sum);