小木棍

链接

这道题时间限制极为严格(260ms),我们只能使用静态数组

先看思路,这道题本质上就是把这些数据分为几个小集合,使这些小集合的元素和相等

要我们求出最小和

我们定义L为目标长度,len为当前长度,假设数组为nums

首先我们需要排序,推荐从大到小,那么L肯定大于或等于nums[0]

所以,我们求最小值就从nums[0]开始

len也推荐从nums[0]开始,因为越长的木棍意味着越少的选择

但是,由于时间极为苛刻,我们必须采取剪枝,除去一些不必要的遍历

1.当总长度(sum)除以L不是整数时,直接跳过

2.当len=0或len=L时依然无法满足条件,直接跳过。

3.当l无妨满足题意,那之后的所有l都无法满足题意,也就是说长度相同则跳过

4.当然,标记数组是必不可少的

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
//count是当前组数,len是当前长度,group是目标组数,target是目标长度,last是当前索引,可以减少遍历时间
bool dfs(int count,int len,bool used[], int group, int target, int nums[], int last) {
	if (count == group) return true;
	if (len == target) return dfs(count + 1, 0, used, group, target,nums,0);//注意,这里last应该是0,因为上一组可能存在跳过元素的情况
	int False = 0;
	for (int i = last;i < n;i++) {
		if (!used[i] && len + nums[i] <= target && nums[i] != False) {
			used[i] = true;
			//返回true的情况只有count=group,如果返回了true,说明这个情况是正确的,可以返回true
			if (dfs(count, len + nums[i], used, group, target, nums,i+1)) return true;
			used[i] = false;
			False = nums[i];
			if (len == 0 || len + nums[i] == target) {
            //len=0不满足题意,说明最长的木棍无论怎么组合都无法满足题意,所以跳过
            //len+nums[i]=target不满足题意(满足了的话会在上面返回true),和len=0类似,其实就是新一组的最长木棍不满足题意
				return false;
			}
		}
	}
	return false;
}
int main() {
	cin >> n;
	int nums[70];
	bool used[70];
	memset(used, 0, sizeof(used));
	int sum = 0;
	for (int i = 0;i < n;i++) {
		cin >> nums[i];
		sum += nums[i];
	}
	sort(nums, nums+n, greater<int>());
	int len = 0;
	for (int l = nums[0];l <= sum;l++) {
		if (sum % l != 0) continue;
		int group = sum / l;
		if (dfs(0, 0, used, group, l, nums,0)) {
			cout << l;
			return 0;
		}
	}
}

时间复杂度:算不来,鬼知道什么时候剪枝了

空间复杂度:O(n)

全部评论

相关推荐

01-05 09:14
同济大学 Java
心碎一号线:我要是9✌🏻我就选保研,保研了大四再找实习,实习之后,如果觉得自己不适合互联网工作模式,还能有其他选择,如果实习后决定了走互联网,也能提升学历提高竞争力
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务