单调队列优化的速度比二进制优化还要高
如果对单调队列优化的多重背包不太熟悉,可参考博文
单调队列优化多重背包(全网最详细解析)_秦三马和他的CF生涯的博客-CSDN博客
首先,原点到一个位置的时间与能量消耗是相同的,都是二倍的(i+j),那我们完全就可以把其看做背包物体的体积,那么背包总体积是多少呢,显然是时间与能量-1的最大值,题目要求能量不能为0,所以我们只能使用总能量-1的能量。
注意一些细节即可,例如前后两个矩阵可能并不一一对应,也就是桃树不为零时,次数可能为0,我们只需要把两者都不为零的情况纳入讨论即可
#include <iostream>
using namespace std;
typedef long long int ll;
typedef struct
{
ll cnt,w,v;
}tree;
tree s[100000+10];
int len;
ll a[1010][1010],b[1010][1010],V,q1[100000],q2[100000],dp[100000];
int main()
{
int n,m;
ll V1,V2;
cin>>n>>m>>V1>>V2;
V=min(V1,V2-1);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>b[i][j];
if(a[i][j]&&b[i][j])
{
s[len].cnt=b[i][j];
s[len].w=a[i][j];
s[len].v=(i+j)<<1;
len++;
}
}
}
int head=0,tail=0;
for(int i=0;i<len;i++)
{
ll v=s[i].v;
ll c=V/v;
c=min(c,s[i].cnt);
ll k=V/v;
for(ll d=0;d<v;d++)
{
head=tail=0;
k=(V-d)/v;
for(int j=0;j<=k;j++)
{
while(head<tail&&dp[j*v+d]-j*s[i].w>=q2[tail-1])
tail--;
q1[tail]=j;
q2[tail]=dp[j*v+d]-j*s[i].w;
tail++;
while(head<tail&&q1[head]<j-c)
head++;
dp[j*v+d]=max(dp[j*v+d],q2[head]+j*s[i].w);
}
}
}
cout<<dp[V];
return 0;
}