我在互联网上发现了以下问题,并想知道我将如何解决它:
问题:没有重新排列的整数分区
输入:非负数的排列S {s 1 ,. 。 。 ,s n }和一个整数k。
输出:将S分区为k个或更少的范围,以最大限度地减少最大值 所有k个或更少范围的总和, 没有重新排序任何 号。*
请帮助,看起来很有趣的问题......我实际上花了很多时间,但没有看到任何解决方案..
答案 0 :(得分:21)
让我们尝试使用动态编程解决问题。
注意:如果 k> n 我们只能使用 n 区间。
当 S = { s 1 d [i] [j] 是问题的解决方案>,..., 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;
}
答案 1 :(得分:8)
这个问题是从Steven Skiena的书“The Algorithm Design Manual”中逐字记录下来的。您可以在Google Books上阅读详细讨论及其解决方案。更好的是,buy the book。