ABC 285 E

题面

在某个世界里,一周有 $ N $ 天。
有一个工厂,为了最大化工人的产出,决定合理安排工作日和休息日。
他们根据统计,发现:
对于每个工作日,如果最近的一个休息日距离他有 $ i $ 天,则产出为 $ A_i $ ;
对于每个休息日,产出为 0。
问一周的最大产出。

思路

dp!dp!dp!
设 $ f_i $ 为前 $ i $ 天的最大总产出(第 $ i $ 天是假期),那么我们遍历 $ i \in 1 \ldots n $ ,
设 $ j $ 为假期与假期间的长度,则可得转移方程 $ f_i = f_{i - j - 1} + \operatorname{calc} (j) $ ,其中 $ \operatorname{calc} (j) $ 表示长度 $ j $ 的一段的总产出。
$ \operatorname{calc} $ 函数可以直接用前缀和求。
那么就完了。

代码

// Problem: E - Work or Rest
// Contest: AtCoder - AtCoder Beginner Contest 285
// URL: https://atcoder.jp/contests/abc285/tasks/abc285_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;

long long a[10005];
long long pre[10005];
long long f[10005];

long long calc(long long len) {
	if (len & 1) {
		return pre[len / 2] + pre[len / 2 + 1];
	} else {
		return pre[len / 2] + pre[len / 2];
	}
}

int main() {
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%lld", &a[i]);
		pre[i] = pre[i - 1] + a[i];
		a[i + n] = a[i];
	}
	for (int i = n + 1; i <= 2 * n; i++) {
		pre[i] = pre[i - 1] + a[i];
	}
	long long ans = -0x3f3f3f3f3f3f3f3fll;
	for (int i = 2; i <= n; i++) {
		f[i] = -0x3f3f3f3f3f3f3f3fll;
		for (int j = 0; j < i; j++) {
			f[i] = max(f[i], f[i - j - 1] + calc(j));
		}
	}
	printf("%lld", f[n]);
}
posted @ 2023-01-16 16:42  A-Problem-Solver  阅读(39)  评论(0编辑  收藏  举报