题目的主干意思是: 一个工厂能够生产6种不同大小的产品, 分别是1*1, 2*2, 3*3, 4*4, 5*5, 6*6. 而工厂的主要业务是快递这些产品, 但是只有一种6*6规格的包装. 所有为了节省成本, 在向顾客寄出产品时, 希望用最少的包装.
输入(每一行分别为各种产品的数量, 以6个0做为结束):
0 0 4 0 0 1 7 5 1 0 0 0 0 0 0 0 0 0
输出(最少需要6*6的包装的数量):
2 1
思路如下:
1. 6*6刚好并且只能占用一个包装, 4*4, 5*5得占用一个包装并留下一些空间, 这些空间下面再考虑.
2. 4个3*3可以构成一个6*6, 剩下的3*3得占用一个包装并留下一些空间, 这些空间下面再考虑.
3. 对于5*5剩下的空间, 我们只需要考虑1*1, 因为只能放得下1*1. 对于4*4虽然可以看成1*1或者2*2, 但是显然看成只能容纳2*2比较容易, 而对于3*3就比较麻烦,
1个3*3可以容纳 1个2*2和5个1*1, 2个3*3可以容纳 3个2*2和6个1*1, 3个3*3可以容纳 5个2*2和7个1*1(n22=2n-1, n11=n*9-4(2n-1)). 这样对于原来有6种产
品的情况变成了只有1*1和2*2两种情况.
4. 把上面2*2的空间计算出来 和 提供输入进行比较, 如果2*2的空间还有多的, 那么可以给1*1用, n11= n11 + 剩下的n22*4.如果不够, 下面再考虑.
5. 那现在就简单了, 我们只有1*1了, 和输入的数据进行比较, 如果处理完之后还有剩余或者刚好就不需要再增加包装了. 但如果不够, 下面再考虑.
6. 现在我们可能还有一堆多余的1*1和2*2, 由于2*2能完美构成一个6*6, 而1*1能完美构成一个2*2. 那我们只用考虑((剩下n22 * 4 + 剩下n11) + 35) / 36的值(+35构成向上取整)
解决方法:
由1,2,3可知初始total=n66+n55+n44+(n33+3)/4
计算完了4,5之后
total+=((剩下n22 * 4 + 剩下n11) + 35) / 36
代码:
#include <stdio.h>
#include <stdlib.h>
int i = 0, res[3000];
int main(void) {
int a[6] = {1, 0, 1, 2, 0, 0}, x = 0, y = 0, z = 0, ly, lz;
int total = a[5];
while(1) {
/*5*5:11个1*1
*4*4:5个2*2
*3*3:4个3*3 1,5 3,6 5,7*/
ly = lz = 0;
total = 0;
scanf("%d %d %d %d %d %d", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]);
if(a[0] == 0&&a[1] == 0&&a[2] == 0&&a[3] == 0&&a[4] == 0&&a[5] == 0) {
a[i] = 0;
break;
}
total += a[5] + a[4] + a[3] + (a[2] + 3) / 4;//4个3*3可以组成一个6*6, 如果有多出, 应该向上取整
x = (4 - a[2] % 4) % 4;//提供多少个3*3, 范围应该是0-3
y = a[3] * 5;//提供多少个2*2
z = a[4] * 11;//提供多少个1*1
if(x > 0) {
y += 2 * x - 1;//3*3的空 能提供多少个2*2
z += (x * 9 - (2 * x - 1) * 4);//3*3的空 除了提供2*2剩下的空还可以提供1*1
}
if(a[1] > y) {
ly += a[1] - y;//如果已有的2*2比 提供的多, 那ly就是多出的部分
} else {
z += (y - a[1]) * 4;//如果2*2处理完了, 那把剩下个2*2空间换成1*1
}
if(a[0] > z) {
lz += a[0] - z;//如果已有的1*1比 提供的多, 那lz就是多出的部分
}
total += ((ly * 4 + lz) + 35) / 36;
res[i++] = total;
}
i = 0;
while(res[i] != 0) {
printf("%d\n", res[i++]);
}
return EXIT_SUCCESS;
}