HDU1003解题报告
给定一串数字,要求子序列和最大的值。这个子序列是连续的。要不然,就直接选取全是正值的加和即可。我开始很直接的就想到一个O(n^2)的算法,因为子序列又开始位置i和结束位置j。我就定义了一个二维数组,索引就是位置,例如,a[i][j]表示,子序列i到j的和,然后遍历一边二维数组,得到最大的值。代码如下:
#include
using namespace std;
int main() {
int t, n, a[100001];
cin >> t;
int index = 1;
while (index <= t) {
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i];
int max = -100000001, x = -1, y = -2, last = -1;
for (int i = 1; i <= n; ++i)
for (int j = i; j <= n; ++j) {
int tmp = -1;
if (i == j) {
tmp = a[i];
} else
tmp = last + a[j];
if (tmp > max) {
max = tmp;
x = i;
y = j;
}
last = tmp;
}
cout << "Case " << index << ":" << endl;
cout << max << " " << x << " " << y;
if (index != t)
cout << endl;
++index;
}
return 0;
}
O(n^2)我自己也没想着能过,所以采用动态规划改进,递归形式很简单,如下:
dp[i] = max(dp[i - 1], a[i])------(1)
很简单,不解释。同时需要使用s和e数组存储每个d[i]的起始位置。具体实现代码如下:
#include
using namespace std;
int main() {
int t, n;
cin >> t;
int index = 1;
while (index <= t) {
cin >> n;
int a[n + 1], dp[n + 1], s[n + 1], e[n + 1];
for (int i = 1; i <= n; ++i)
cin >> a[i];
dp[0] = 0;
s[0] = 1;
for (int i = 1; i <= n; ++i) {
int tmp = dp[i - 1] + a[i];
if (tmp >= a[i]) {
dp[i] = tmp;
s[i] = s[i - 1];
} else {
dp[i] = a[i];
s[i] = i;
}
e[i] = i;
}
int max = -100000001, x = -1, y = -1;
for (int i = 1; i <= n; ++i) {
if (dp[i] > max) {
max = dp[i];
x = s[i];
y = e[i];
}
}
cout << "Case " << index << ":" << endl;
cout << max << " " << x << " " << y << endl;
if (index != t)
cout << endl;
++index;
}
return 0;
}
浙公网安备 33010602011771号