【题解】A18535.来自领导的烦恼
思路:本题可以使用动态规划或递归的方式来实现,本质上是一道01背包的变型题。假设一共有\(n\)名员工,每一位员工的技能水平用\(a[i]\)表示。要使得两个部门的员工技能总和之差最小,意思就是尽可能地将一个部门的技能之和”凑“到\(\sum\limits_{i=1}^{n}a[i] \times \frac{1}{2}\),也就是所有员工技能总和的一半。套用背包问题的模板,每一位员工就是每一件“物品”,背包的容量就是“所有员工技能总和的二分之一”。
时间复杂度分析:本题通过两个for
循环来填写dp表格,外层循环遍历每一个员工,内层循环遍历所有员工的技能水平之和。外层循环执行\(n\)次,内层循环执行\(a[i]/2\)次。因此,本道题目的时间复杂度为\(\Theta(n\times \sum\limits_{i=1}^{n}a[i]/2)\),约为\(O(n^2)\)。
参考代码:
参考代码在01背包的基础上进行了内存优化,将二维dp数组转换成了一维dp数组。其中:
arr[i]
表示第i个员工的技能水平。sum
表示所有员工技能水平之和。
#include <iostream>
#include <cmath>
using namespace std;
int n, sum;
int arr[5005], dp[100005];
int main(){
cin >> n;
for (int i=1; i<=n; i++) {
cin >> arr[i];
sum += arr[i];
}
int half = sum / 2;
for (int i=1; i<=n; i++){
for (int j=half; j>=0; j--){
if (j - arr[i] >= 0){
dp[j] = max(dp[j], dp[j-arr[i]] + arr[i]);
}
}
}
cout << sum - 2*dp[half] << endl;
return 0;
}