多重背包(单调队列(滑动最大值)+二进制方法)

自己复习用
1.单调队列法
详见《挑战》p340
然后我其实不懂为什么在deq[s]==j-m[i]时去掉队首,过几天懂了我来更新,如果你知道的话请告诉我qq2298763866

#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn=200;
const int maxm=10100;
const int maxw=10100;
int n,wgh;
int w[maxn];
int v[maxn];
int m[maxn];
int dp[maxn+maxm];
int main()
{
    scanf("%d",&n);
    for(int i=0;i"%d%d%d",&w[i],&v[i],&m[i]);
    }

    scanf("%d",&wgh);

    int deq[maxn];
    int deqv[maxn];
    int s=0;
    int t=0;
    for(int i=0;ifor(int a=0;as=0;
            t=-1;
            for(int j=0;j*w[i]+a<=wgh;j++)
            {
                int b=dp[j*w[i]+a]-j*v[i];//加入单调队列的是b值
                while(s<=t && deqv[t]<=b)
                {
                    t--;
                }
                t++;
                deq[t]=j;
                deqv[t]=b;
                dp[j*w[i]+a]=deqv[s]+j*v[i];
                //
                if(deq[s]==j-m[i])
                {
                    s++;
                }
                //
            }
        }
    }
    printf("%d\n",dp[wgh]);
    return 0;
}

2.二进制背包
9讲上有 不过自己写还是第一次

#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn=200;
const int maxm=10100;
const int maxw=10100;
int n,wgh;
int w[maxn];
int v[maxn];
int m[maxn];
int dp[maxn+maxm];
int main()
{
    scanf("%d",&n);
    for(int i=0;iscanf("%d%d%d",&w[i],&v[i],&m[i]);
    }

    scanf("%d",&wgh);

    int num=0;
    for(int i=0;ifor(int j=1;num>0;j<<=1)
        {
            int mul=min(j,num);
            for(int k=wgh;k>=w[i]*mul;k--)
            {
                dp[k]=max(dp[k],dp[k-w[i]*mul]+mul*v[i]);
            }
            num-=mul;
        }
    }
    printf("%d\n",dp[wgh]);
    return 0;
}

理由等我过几天懂了再来更

你可能感兴趣的:(算法,noip,动态规划,挑战程序设计竞赛1)