思路
发现直接算答案很麻烦,我们可以记录最大魔力,然后找到满足最大魔力非负的最大的鸟数。
令 fi,jf_{i,j}fi,j 表示前 iii 棵树上,总共召唤 jjj 只鸟的最大魔力。易得 fi,j=maxk=0cimin(mxx,min(mx,fi−1,j−k+X⋅[i≠1])−costi⋅k)f_{i,j}=\max_{k=0}^{c_i}\min(mxx,\min(mx,f_{i-1,j-k}+X\cdot[i\neq1])-cost_i\cdot k)fi,j=maxk=0cimin(mxx,min(mx,fi−1,j−k+X⋅[i=1])−costi⋅k)。有点绕,解释一下,mxmxmx 表示上一棵树走完后的魔力上限,mxxmxxmxx 表示这一棵树走完后的魔力上限。计算也很简单:mx=W+B⋅(j−k),mxx=W+B⋅jmx=W+B\cdot (j-k),mxx=W+B\cdot jmx=W+B⋅(j−k),mxx=W+B⋅j。
这道题最好不要压成一维,否则很可能会输出 ∑i=1Nci\sum_{i=1}^N c_i∑i=1Nci。
代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int n, w, b, x;
int c[1010];
long long cost[1010];
long long f[1010][10010];
int main()
{
cin >> n >> w >> b >> x;
for (int i = 1; i <= n; i++)
cin >> c[i];
for (int i = 1; i <= n; i++)
cin >> cost[i];
int s = 0;
memset(f, -0x3f, sizeof(f));
f[0][0] = w;
for (int i = 1; i <= n; i++)
{
for (int j = 0; j <= c[i]; j++)
for (int k = j; k <= s + j; k++)
{
if (f[i - 1][k - j] < 0) continue;
long long mx = w + 1LL * b * (k - j);
long long mxx = w + 1LL * b * k;
int X = 0; if (i != 1) X = x;
long long val = min(mx, f[i - 1][k - j] + X);
val -= cost[i] * j;
f[i][k] = max(f[i][k], min(mxx, val));
}
s += c[i];
}
for (int i = s; i >= 0; i--)
if (f[n][i] >= 0)
{
cout << i << endl;
return 0;
}
return 0;
}