题目描述
公司准备在年会上开展抽奖活动。他们购买了若干个奖品,每个奖品都有一个价格,用一个正整数数组表示。在抽奖环节,公司准备设置一等奖、二等奖和三等奖,每个等级设置一个奖品,并将所有奖品分成三份大礼包。公司希望尽可能地减小一等奖和三等奖之间的价格差异,同时满足一等奖总价格大于二等奖总价格,二等奖总价格大于三等奖总价格。
输入描述
- 第一行:正整数
n
,表示奖品的数量,取值范围[3,16)
。 - 第二行:一个正整数数组
array
,每个元素表示奖品的价格,取值范围[1,1000]
。
输出描述
一个非负整数,表示一等奖和三等奖的差值,没有方案返回 0
。
用例输入
3
5 4 2
3
4
10 5 4 2
5
分配方案有多种,一等奖和三等奖差值最小的方案是 10,6,5
。
解题思路
-
暴力搜索:
- 使用深度优先搜索(DFS)枚举所有可能的分配方案。对于每个奖品,尝试将其分配到一等奖、二等奖或三等奖中。
- 在搜索过程中,剪枝以减少不必要的计算。例如,如果当前分配方案已经无法满足
x > y > z
的条件,则直接跳过该方案。 - 记录所有满足条件的方案中,一等奖和三等奖价格差的最小值。
-
剪枝优化:
- 在分配过程中,实时计算剩余未分配的奖品总价值。如果当前分配方案即使加上所有剩余奖品也无法满足
x > y > z
的条件,则直接跳过该方案。
- 在分配过程中,实时计算剩余未分配的奖品总价值。如果当前分配方案即使加上所有剩余奖品也无法满足
代码
#include <iostream>
#include <vector>
#include <queue>
#include <sstream>
#include <string>
#include <stack>
#include <algorithm>
using namespace std;
int n;
vector<int> nums(20);
int res = 1000000;
// 当前遍历到的下标 一等 二等 三等 剩余未用的价格
void dfs(int cur, int i, int j, int k, int s) {
if (cur == n) {
// 结束
if (i > j && j > k) {
res = min(res, i - k);
}
return;
}
// 全部给了也不符合结果的直接pass
if (i + s < j || i + s < k || j + s < k) return;
// 开始分配 暴力搜索
dfs(cur + 1, i + nums[cur], j, k, s - nums[cur]);
dfs(cur + 1, i, j + nums[cur], k, s - nums[cur]);
dfs(cur + 1, i, j, k + nums[cur], s - nums[cur]);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
int all = 0;
for (int i = 0; i < n; i++) {
cin >> nums[i];
all += nums[i];
}
dfs(0, 0, 0, 0, all);
if (res == 1000000) res = 0; // 如果没有找到方案,返回0
cout << res;
}