Max Sum Plus Plus HDU - 1024(DP+滚动数组)

题目传送门

题意:

给你n个数(用数组a表示),要你把这n个数分为m段,段与段之间互不重叠,求m段和的最大值。

思路:

如果直接开二维数组存dp的话,n<=1e6,肯定会爆。不过还是先说说原理吧:

用dp[i][j]表示:在选第j个数字的情况下,把前j个数字分成i组的最大和。而dp[i][j]的更新,取决于a[j]到底是加入邻近的段,还是自成一段。
所以推出动态转移方程:dp[i][j] = max(dp[i][j-1], dp[i-1][k]) + a[j];

而要解决爆内存的问题,就需要滚动数组。首先通过观察,不难发现,当前状态只和上一个状态有关。所以只需要记录当前状态和上一个状态即可。

Code:

int a[1000005], n, m;
int dp[1000005], sum[1000005];
int main() {
    
    
	while (scanf("%d%d", &m, &n) != EOF) {
    
    
		for (int i = 1; i <= n; i++) read(a[i]), dp[i] = 0, sum[i] = 0;
		int ans;
		for (int i = 1; i <= m; i++) {
    
    
			ans = -INF;
			for (int j = i; j <= n; j++) {
    
    
				dp[j] = max(sum[j-1], dp[j-1]) + a[j];
				sum[j-1] = ans;
				ans = max(ans, dp[j]);
			}
		}
		cout << ans << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liudashuai666/article/details/113338406