洛谷 P1858 多人背包 解题报告

匿名 (未验证) 提交于 2019-12-03 00:40:02

求01背包前k优解的价值和

第一行三个数\(K\)\(V\)\(N\)

接下来每行两个数,表示体积和价值

前k优解的价值和

对于100%的数据,$ K\le 50,V\le 5000,N\le 200$


算是积累见识吧,有些类型的题不见过一面估计比较难想

方程为\(dp[i][j][k]\)代表前\(i\)中在装了\(j\)时第\(k\)优值

如何转移呢

\(dp[i][j]\)来说,由\(dp[i-1][j]\)\(dp[i-1][j-w]+c\)转移

即我们从\(dp[i-1][j][1...k]\)\(dp[i-1][j-w][1...k]+c\)中选出前\(k\)大的给\(dp[i][j][1...k]\)

用到了归并排序的思想


Code:

#include <cstdio> #include <cstring> int max(int x,int y){return x>y?x:y;} int min(int x,int y){return x<y?x:y;} const int inf=0x3f3f3f3f; int k,v,n,dp[52][5010],c,w,tmp[52]; int main() {     memset(dp,-0x3f,sizeof(dp));     scanf("%d%d%d",&k,&v,&n);     dp[1][0]=0;     for(int i=1;i<=n;i++)     {         scanf("%d%d",&w,&c);         for(int j=v;j>=w;j--)         {             int l1=1,l2=1,cnt=0;             while(l1+l2<=k+1)             {                 if(dp[l1][j]>dp[l2][j-w]+c)                     tmp[++cnt]=dp[l1++][j];                 else                     tmp[++cnt]=dp[l2++][j-w]+c;             }             for(int l=1;l<=k;l++) dp[l][j]=tmp[l];         }     }     int ans=0;     for(int i=1;i<=k;i++)         ans+=dp[i][v];     printf("%d\n",ans);     return 0; }

2018.7.13

原文:https://www.cnblogs.com/ppprseter/p/9305197.html

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!