HDU 2639 (01背包第k优解)

/*
01背包第k优解问题
f[i][j][k] 前i个物品体积为j的第k优解
对于每次的ij状态 记下之前的两种状态 i-1 j-w[i] (选i) i-1 j (不选i) 分别k个 
然后归并排序并且去重生成ij状态的前k优解 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1010
using namespace std;
int T,n,m,k,c[maxn],v[maxn],f[maxn][100],x[maxn],y[maxn],a,b,z;
int init()
{
    int x=0;bool f=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    if(f)return -x; return x;
}
int main()
{
    T=init();
    while(T--)
      {
          memset(f,0,sizeof(f));
          n=init();m=init();k=init();
          for(int i=1;i<=n;i++)
            v[i]=init();
          for(int i=1;i<=n;i++)
            c[i]=init();
          for(int i=1;i<=n;i++)
            {
                for(int j=m;j>=c[i];j--)
                  {
                    for(int l=1;l<=k;l++)
                      {
                        x[l]=f[j][l];
                        y[l]=f[j-c[i]][l]+v[i];
                      }
                    a=b=z=1;
                    x[k+1]=y[k+1]=-1;
                    while(z<=k&&(x[a]!=-1||y[b]!=-1))
                      {
                        if(x[a]<y[b])f[j][z]=y[b],b++;
                        else f[j][z]=x[a],a++;
                        if(f[j][z]!=f[j][z-1])z++;
                      }
              }
          }
        printf("%d
",f[m][k]);
      }
    return 0;
}
原文地址:https://www.cnblogs.com/yanlifneg/p/5562666.html