多人背包

       题目在这里qwq

题目描述:求01背包前k优解的价值和

输入格式:第一行三个数k,v,n 接下来n行每行两个数 体积和价值

输出格式:前k优解的价值和

    

正解:

  在01背包的基础上再加上一个维度

  f[m][k]:重量为m的第k优解  注意要初始化为-inf 而不是0 因为背包要填满

  用tmp[k] 来存当前求的体积为m时的第k优解 最后用它来更新f[m][k]即可

  <下面的栗子中用到的数组(也是代码里的数组)>:

    a[i] 第i件物品的体积;b[i] 第i件物品的价值  

    然后以下的转移的外层循环就是一般01背包的循环 具体见代码

        假设我们现在要求f[m][k] (k=1,2,…,5)

  f[m][1]显然只能为max(f[m][1],f[m-a[i]][1]+b[i])

  若f[m][1]=f[m-a[i]]+b[i] 那么f[m][2]=max(f[m][1],f[m-a[i]][2]+b[i])

        若f[m][1]=f[m][1] 那么f[m][2]=max(f[m][2],f[m-a[i]][1]+b[i])

  以此类推 其实应该还是比较好理解的 但是感觉写好code有一点点难

   

#include<iostream>
#include<algorithm>
#include<cstdio>
#define go(i,a,b) for(register int i=a;i<=b;i++)
#define goo(i,a,b) for(register int i=a;i>=b;i--)
#define inf 210000000
using namespace std;
int read()
{
  int x=0,y=1;char c=getchar();
  while(c<'0'||c>'9') c=getchar();
  while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
  return x*y;
}
int k,v,n,t,t1,t2,ans,a[210],b[210],f[5010][60],tmp[60];
int main()
{
    k=read();v=read();n=read();
    go(i,1,n) a[i]=read(),b[i]=read();
    go(i,0,v) go(j,1,k) f[i][j]=-inf;
    f[0][1]=0;
    go(i,1,n)
       goo(j,v,a[i]) {
         t1=1;t2=1;t=0; //t1,t2 相当于两个指针吧 具体理解见上面分析中的栗子
         while(t<=k) {
           if(f[j][t1]<f[j-a[i]][t2]+b[i]) tmp[++t]=f[j-a[i]][t2++]+b[i];
           else tmp[++t]=f[j][t1++];
         }
         go(x,1,k) f[j][x]=tmp[x];
    }
    go(i,1,k) ans+=f[v][i];
    printf("%d",ans);
    return 0;
}
View Code

 

 

 

 

posted @ 2019-01-24 16:26  DTTTTTTT  阅读(149)  评论(0编辑  收藏  举报