Codeforces 922E

有N颗树,第i颗树上有(c_i)只鸟,召唤师每召唤一只该树上的鸟,法力上限增加B(常数),消耗法力(cost_i)
召唤师从第1颗树到第N颗,每到一棵树回复法力值X,求最多召唤多少只鸟
input: (n, W, B, X(1 leq n leq 10^3, 0 leq W, B, X, leq 10^9))
(c_1, c_2...c_n(0 leq c_i leq 10^4))
(cost_1, cost_2...cost_n(0 leq cost_i leq 10^9))

第一想法显然用(dp[N][sum c_i])表示最终答案
显然需要想明白,这个复杂度是可以接受的
虽然是三重循环,但复杂度只有(O(nsum _{i=1} ^n c_i))

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;

const int maxn = 1e3 + 10;
const int maxm = 1e4 + 10;

int A[maxn], cost[maxn];
LL dp[maxn][maxm];

int sum, ans;
LL N, W, B, X;

int main() {
	scanf("%lld%lld%lld%lld", &N, &W, &B, &X);
	for (int i = 1; i <= N; i++) scanf("%d", &A[i]), sum += A[i];
	for (int i = 1; i <= N; i++) scanf("%d", &cost[i]);
	memset(dp, -1, sizeof(dp)); ans = 0;
	dp[0][0] = W;
	for (int i = 1; i <= N; i++) {
		for (int j = 0; j <= sum; j++) {
			for (int k = 0;  k <= min(j, A[i]); k++) {
				if (dp[i - 1][j - k] == -1) continue;
				LL t = min(W + (j - k) * B, dp[i - 1][j - k] + X) - (LL)cost[i] * k;
				if (t < 0) continue;
				dp[i][j] = max(dp[i][j], min(W + j * B, t));
				ans = max(ans, j);
			}
		}
	}
	printf("%d
", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/xFANx/p/9551011.html