hdu2191(单调队列优化dp,多重背包)

单调队列优化

这个dp可以写成这么样

对于第i个物品

dp[j+(k)*w(i)]=max(dp[j+k*w(i)]-k*w(i))+(k)*v[i]。

k的大小为1<=k<=m[i]

坑1、push_back(k)应该写在计算时候的前面

2、注意滚动数组的使用

 

#include
using namespace std;
typedef long long ll;
const int maxn=1e5+7;
int w[maxn],v[maxn],num[maxn];
int list1[maxn];
int val[maxn];
int dp[maxn],deq[maxn];
int main(){
    int i,j,k,f1,f2,f3,f4,t1,t2,t3,t4,n,m,T;
    //freopen("in.txt","r",stdin);
    //freopen("out1.txt","w",stdout);
    scanf("%d\n",&T);
    while(T--){
    memset(dp,0,sizeof(dp));
    scanf("%d %d",&n,&m);
    for(i=1;i<=m;i++){
        scanf("%d %d %d",&w[i],&v[i],&num[i]);
    }
    int s,t;
    for(i=1;i<=m;i++){
        for(j=0;js&&val[k]>=val[list1[t-1]]){//t-1表示头,比其优就挤出来
                t--;
            }
            deq[t]=k; //从0开始,因为s是第一个结果,不从0开始不知道s表示什么
            list1[t++]=k;
            dp[j+k*w[i]]=max(dp[j+k*w[i]],val[list1[s]]+k*v[i]);
            while(t>s&&k-deq[s]>=num[i]){ //每次都是值会删除一个值
            s++;
            }
        }
    }
    }
    printf("%d\n",dp[n]);
    }
    return 0;
}

 

 

 

 

 

你可能感兴趣的:(hdu2191(单调队列优化dp,多重背包))