附上计蒜客官方讲解:
HDU 2191为例
#include<bits/stdc++.h>
using namespace std;
int n,m,l,r;
int dp[110],q[110],num[110];
int main()
{
int cs,v,w,c;
scanf("%d",&cs);
while(cs--){
scanf("%d%d",&m,&n); //m表示容量,n表示种类。
for(int i=0;i<=m;i++){
dp[i]=0;
}
for(int i=1;i<=n;i++){
scanf("%d%d%d",&v,&w,&c); //v 体积 w 价值 c 数量
if(c>m/v) c=m/v;
for(int b=0;b<v;b++){
l=r=1;
for(int t=0;t<=(m-b)/v;t++){
int tmp=dp[t*v+b]-t*w;
while(l<r&&q[r-1]<=tmp) r--;
q[r]=tmp;
num[r++]=t;
while(l<r&&t-num[l]>c) l++; //滑动区间长度不大于c,因为dp[t*v+b]-t*w既然存在,那么再加c区间的t*w的值肯定能取到
dp[t*v+b]=max(dp[t*v+b],q[l]+t*w); //因为dp中的是t*v+b,所以是q[l]+t*w
}
}
}
printf("%d\n",dp[m]);
}
return 0;
}