C++【动态规划】
#include<iostream>
#include<vector>
using namespace std;
int main()
{int n;cin >> n;vector<int> dp(100000 * 20);vector<int> a(n);int ans = 0, cur = 0;for (int i = 0; i < n; i++){cin >> a[i];ans += a[i];}int sum = ans / 2;for (int i = 0; i < n; i++)for (int j = sum; j >= a[i]; j--)dp[j] = max(dp[j], dp[j - a[i]] + a[i]);cout << ans - dp[sum] * 2 << endl;return 0;
}
C【动态规划】
#include <stdio.h>
#include <stdlib.h>
#define MAXN 100000 * 20
int main()
{int n;scanf("%d", &n);int* dp = (int*)malloc(sizeof(int) * (MAXN + 1));int a[20];int sum = 0, ans = 0;for (int i = 0; i < n; i++){scanf("%d", &a[i]);ans += a[i];}sum = ans / 2;dp[0] = 0;for (int i = 0; i < n; i++)for (int j = sum; j >= a[i]; j--)dp[j] = (dp[j] > dp[j - a[i]] + a[i]) ? dp[j] : dp[j - a[i]] + a[i];printf("%d\n", abs(ans - 2 * dp[sum]));free(dp);return 0;
}
算法介绍:动态规划
首先计算输入数组a的总和,并设定目标和为总和的一半。初始化动态规划数组 dp,其中 dp[j]表示当前考虑了部分元素后,能否组成一个和为 j 的子集。遍历数组 a,对每个元素尝试加入到满足条件的“堆”中(即更新 dp[j]),确保在所有可能的划分方案中找到使得两个堆的和相差最小的情况。最后输出原数组总和与目标和所能达到的最大价值的两倍之差,即两堆之差的最小值。
时间复杂度:o(n^2)
这段代码的时间复杂度主要取决于两个嵌套循环的执行次数。外层循环遍历输入数组 a
的所有元素,其时间复杂度为 O(n)。 内层循环对于数组中的每个元素,会从目标和 sum
开始一直减到当前元素为止,其时间复杂度在最坏情况下是 O(sum),因为对于较大的元素,内层循环可能接近于 sum 次迭代。由于在最坏情况下,sum
可以达到数组元素总和的一半,而数组元素总和与数组大小 n 相关,因此可以假设在极端情况下,sum
与 n 成正比,即 sum = O(n)。所以,总的复杂度是外层循环与内层循环复杂度的乘积,即 O(n * sum) ≈ O(n^2)。这意味着当输入数组规模增大时,算法所需的时间将以二次方的速度增长。