RT 这是下面是没用单调队列的呆毛
没有T的点都过了,正确性应该是能保证的
#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 2e3 + 5; //remember to modify the range of the data!!
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int n, m, T;
ll f[N][N]; //第i天持有j支股票的最大收益
int ap[N], bp[N], as[N], bs[N];
ll mx[N][N];//前i天中,持有j支股票的最大收益
int main(void)
{
int t, mp, w;
cin >> n >> mp >> w;
for(int i = 1; i <= n; i++)
cin >> ap[i] >> bp[i] >> as[i] >> bs[i];
memset(f, -0x3f, sizeof(f));
memset(mx, -0x3f, sizeof(mx));
mx[0][0] = 0;
f[0][0] = 0;
for(int i = 1; i <= n; i++)
{
for(int j = 0; j <= mp; j++)
{
f[i][j] = f[i - 1][j];
for(int k = 1; k <= min(j, as[i]); k++)
{
int pre = max(i - w - 1, 0);
f[i][j] = max(f[i][j] , mx[pre][j - k] - ap[i] * k);
}
for(int k = 1; k <= min(bs[i], mp - j); k++)
{
int pre = max(i - w - 1, 0);
f[i][j] = max(f[i][j], mx[pre][j + k] + bp[i] * k);
}
mx[i][j] = max(mx[i - 1][j], f[i][j]);
}
}
cout << f[n][0];
return 0;
}
然后使用单调队列优化后
wa了
#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 2e3 + 5; //remember to modify the range of the data!!
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int n, m, T;
ll f[N][N];
int ap[N], bp[N], as[N], bs[N];
ll mx[N][N];//所有前i天中,持有j支股票的最大收益
int main(void)
{
int t, mp, w;
cin >> n >> mp >> w;
for(int i = 1; i <= n; i++)
{
// cin >> ap[i] >> bp[i] >> as[i] >> bs[i];
scanf("%d%d%d%d", ap + i, bp + i, as + i, bs + i);
}
memset(f, -0x3f, sizeof(f));
memset(mx, -0x3f, sizeof(mx));
mx[0][0] = 0;
f[0][0] = 0;
deque <pair <ll, int> > q1, q2;
for(int i = 1; i <= n; i++)
{
q1.clear();
q2.clear();
for(int j = 0; j <= mp; j++)
{
f[i][j] = f[i - 1][j]; //不买不卖
int pre = max(i - w - 1, 0); //进行交易时从前面那一天转移
int up = j - 1, low = j - min(j ,as[i]); // low, up表示上下界,单调队列在这个区间找最值
//买
if(up >= 0)
{
while(!q1.empty() && q1.back().first <= mx[pre][up])
q1.pop_back();
q1.push_back({mx[pre][up], up});
while(!q1.empty() && q1.front().second < low)
q1.pop_front();
f[i][j] = max(f[i][j] , q1.front().first - ap[i] * (j - q1.front().second));
}
//卖
up = min(j + bs[i], mp), low = j + 1;
if(j == 0) //第一次先把区间全装进去,后面的只需要每次判一个就行了
{
for(int k = low; k <= up; k++)
{
while(!q2.empty() && q2.back().first <= mx[pre][k])
q2.pop_back();
q2.push_back({mx[pre][k], k});
while(!q2.empty() && q2.front().second < low)
q2.pop_front();
}
}
if(low <= mp)
{
while(!q2.empty() && q2.back().first <= mx[pre][up])
q2.pop_back();
q2.push_back({mx[pre][up], up});
while(!q2.empty() && q2.front().second < low)
q2.pop_front();
f[i][j] = max(f[i][j], q2.front().first + bp[i] * (q2.front().second - j));
}
mx[i][j] = max(mx[i - 1][j], f[i][j]);
}
}
cout << f[n][0];
return 0;
}