我在互联网上发现了以下问题,并想知道如何解决该问题:
问题: 没有重新排列的整数分区 输入: 非负数{s 1,。。。。,s n }和整数k。 输出:将 S划分为k个或更少的范围,以最小化所有k个或更少的范围之和的最大值,而无需重新排列任何数字。*
问题: 没有重新排列的整数分区
输入: 非负数{s 1,。。。。,s n }和整数k。
输出:将 S划分为k个或更少的范围,以最小化所有k个或更少的范围之和的最大值,而无需重新排列任何数字。*
请帮忙,似乎是一个有趣的问题……我实际上花了很多时间,但没有找到任何解决方案。
让我们尝试使用动态编程解决问题。
注意:如果 k > n,_我们只能使用 _n个 间隔。
让我们考虑 d [i] [j] 是当 S = { s 1,…, s i }和 k = j 时问题的解决方案。因此很容易看到:
现在,让我们看看为什么它起作用:
例:
S =(5,4,1,12),k = 2
d [0] [1] = 0,d [0] [2] = 0
d [1] [1] = 5,d [1] [2] = 5
d [2] [1] = 9,d [2] [2] = 5
d [3] [1] = 10,d [3] [2] = 5
d [4] [1] = 22,d [4] [2] = 12
码:
#include <algorithm> #include <vector> #include <iostream> using namespace std; int main () { int n; const int INF = 2 * 1000 * 1000 * 1000; cin >> n; vector<int> s(n + 1); for(int i = 1; i <= n; ++i) cin >> s[i]; vector<int> first_sum(n + 1, 0); for(int i = 1; i <= n; ++i) first_sum[i] = first_sum[i - 1] + s[i]; int k; cin >> k; vector<vector<int> > d(n + 1); for(int i = 0; i <= n; ++i) d[i].resize(k + 1); //point 1 for(int j = 0; j <= k; ++j) d[0][j] = 0; //point 2 for(int i = 1; i <= n; ++i) d[i][1] = d[i - 1][1] + s[i]; //sum of integers from s[1] to s[i] //point 3 for(int i = 1; i <= n; ++i) for(int j = 2; j <= k; ++j) { d[i][j] = INF; for(int t = 1; t <= i; ++t) d[i][j] = min(d[i][j], max(d[i - t][j - 1], first_sum[i] - first_sum[i - t])); } cout << d[n][k] << endl; return 0; }