题目来源
题目描述
题目解析
- 本题与leetcode:698. 划分为k个相等的子集本质上是一样的。
- 本题要求我们返回最多能分成几层(也就是层高),而且要用完所有的积木
- 用完所有的积木:表示所有的积木都要分到对应的层中
- 我们能从参数中得到的信息是:积木的长度,通过这个长度,我们就可以算出总长度
- 那么总长度sum和层高high有什么关系呢?
- 如果sum % high == 0 ,那么表示可以均分,那么每一层的应该分到的长度是sum / high
- 我们可以枚举所有的高度:2、3、4、5、…sum/2,并判断能不能满足 sum % high == 0,如果满足的话就开始尝试分配
- 怎么分配呢?
- 我们已经知道了应该要一共会有层:high(枚举)
- 刚刚我们算出了每一层的的总长度score = sum / high
- 然后开始暴力递归
- 我们可以先计算出sum,然后我们看能不能平分成k层。
#include <utility>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
class Solution{
std::list<std::vector<int>> snake;
// curr为当前正在看的元素
// used为下一个要存放到bucket中的位置
// k表示一共需要分配多少次
bool dfs(std::vector<int>& nums, int cur, std::vector<int>& bucket, int k, int target){
// 结束条件:已经处理完所有球
if (cur == nums.size()) {
return true;
}
// 还有数据待分配
// 从nums[curr]开始做选择
for (int i = 0; i < k; i++) { //遍历k个桶, 查看当前数可以放到哪个桶中
// 如果当前桶和上一个桶内的元素和相等,则跳过
// 原因:如果元素和相等,那么 nums[index] 选择上一个桶和选择当前桶可以得到的结果是一致的
if (i > 0 && bucket[i] == bucket[i - 1]) continue;
if (bucket[i] + nums[cur] <= target) { // 当前元素可以放到桶中
bucket[i] += nums[cur];
if (dfs(nums, cur + 1, bucket, k, target))
return true;
bucket[i] -= nums[cur];
}
}
return false;
}
public:
int process(std::vector<int> &nums){
int sum = 0;
for(int num : nums){
sum += num;
}
int res = -1;
std::sort(nums.begin(), nums.end());
for (int i = 2; i <= sum / 2; ++i) {
if(sum % i != 0){
continue;
}
std::vector<int> bucket(i, 0); // 建立一个桶
if(dfs(nums, 0, bucket, i, sum / i)){
res = std::max(res, i);
}
}
return res;
}
};
int main(){
std::vector<int> num {9, 9, 9, 5, 3, 2, 2, 2, 2, 2};
num = {3, 6, 3, 3, 3};
Solution obj;
cout << obj.process(num) << endl;
}
动态规划
这个问题可以转换为背包问题。
首先计算和sum,排序,选取最大的maxVal作为墙的第一层,
- 如果 sum % maxVal == 0,代表可以这样划分,
- 如果不可以则 maxVal += maxVal + nuns[i], 加上最小的。
可以化分的层数就为 cnt = sum / maxVal
背包容量为:sum /= cnt
#include <utility>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
class Solution{
public:
int process(std::vector<int> &nums){
int n = nums.size();
if(n <= 1){
return -1;
}
std::sort(nums.begin(), nums.end());
int maxVal = nums[n - 1];
int sum = 0;
for(int num : nums){
sum += num;
}
for (int i = 0; i < n - 1; ++i) {
if(sum % maxVal == 0){
break;
}else{
maxVal += nums[i];
}
}
int cnt = sum / maxVal;
sum /= cnt;
std::vector<std::vector<bool>> dp(n + 1 , std::vector<bool>(sum + 1, false));
for (int i = 0; i <= n; ++i) {
dp[i][0] = true;
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= sum; j++){
if(j - nums[i - 1] < 0){
dp[i][j] = dp[i - 1][j];
}else{
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i - 1]];
}
}
}
return dp[n][sum] && cnt != 1 ? cnt : -1;
}
};
int main(){
std::vector<int> num {9, 9, 9, 5, 3, 2, 2, 2, 2, 2};
num = {3, 6, 3, 3, 3};
Solution obj;
cout << obj.process(num) << endl;
}