开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情
放置盒子
有一个立方体房间,其长度、宽度和高度都等于 n 个单位。请你在房间里放置 n 个盒子,每个盒子都是一个单位边长的立方体。放置规则如下:
- 你可以把盒子放在地板上的任何地方。
- 如果盒子
x需要放置在盒子y的顶部,那么盒子y竖直的四个侧面都 必须 与另一个盒子或墙相邻。
给你一个整数 n ,返回接触地面的盒子的 最少 可能数量 。
示例 1:
输入: n = 3
输出: 3
解释: 上图是 3 个盒子的摆放位置。
这些盒子放在房间的一角,对应左侧位置。
示例 2:
输入: n = 4
输出: 3
解释: 上图是 3 个盒子的摆放位置。
这些盒子放在房间的一角,对应左侧位置。
示例 3:
输入: n = 10
输出: 6
解释: 上图是 10 个盒子的摆放位置。
这些盒子放在房间的一角,对应后方位置。
思路
要求最少的底面积。
首先,要明确一点的是,当前底面积为k,可以容纳多少个矩形?
这一点可能不是很好算,但是,可以发现,肯定是靠墙角堆积是最优的,只用考虑两个面。
在这个的基础上,观察一下添加底层一排矩形这个行为可以增加多少个呢?
可以发现,若是底层增加了k个矩形,那么上层可以增加k-1个矩形,对于每一层来说,都有这个规律。
那么,若是底面积增加了k,则总体矩形个数增加
限制:每一层必须按照按墙角对齐码放满的情况下(最优情况)
每一层码放满的情况下,底面积增加方式为 1, 3, 6, 10, ...
也就是说,第k次增加底面积的是k,总体增加 个矩形
总共所以的矩形个数为:
用打表的方式大概看一下范围增长速度:
vector<long long> cur, sum;
cur.push_back(1), sum.push_back(1);
for (int i = 2; i <= 2000; i ++) {
cur.push_back(cur.back() + i);
sum.push_back(sum.back() + cur.back());
}
发现2000以内完全够用,所以,可以直接进行递推出大于n个矩形的那一个底面积
然后在慢慢逼近。
代码
class Solution {
public:
int minimumBoxes(int n) {
int cur = 1, sum = 1, i = 1;
for (; n > sum; ) {
i ++;
cur += i;
sum += cur;
}
if (n == sum) return cur;
n -= sum - cur;
int k = 0;
while (++ k)
if (n <= (k * (k + 1) / 2))
return cur - i + k;
return 114514;
}
};