解题:洛谷 p1858 多人背包

题面

设$dp[i][j]$表示容量为$i$时的第$j$优解,因为是优解,肯定$dp[i][j]$是随着$j$增大不断递减的,这样的话对于一个新加进来的物品,它只可能从两个容量的转移的前$k$优解中转移过来,所以每次用两个指针扫一下转移过来就好了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=5005,K=52;
 6 int vol[N],val[N],tmp[K],dp[N][K];
 7 int n,v,k,tot,p1,p2,ans;
 8 int main ()
 9 {
10     scanf("%d%d%d",&k,&v,&n);
11     for(int i=1;i<=n;i++)
12         scanf("%d%d",&vol[i],&val[i]),tot+=vol[i];
13     memset(dp,0xcf,sizeof dp),dp[0][1]=0;
14     for(int i=1;i<=n;i++)
15         for(int j=v;j>=vol[i];j--)
16         {
17             p1=p2=1;
18             for(int h=1;h<=k;h++)
19             {
20                 int c=(dp[j-vol[i]][p1]+val[i]>dp[j][p2]);
21                 tmp[h]=c?dp[j-vol[i]][p1++]+val[i]:dp[j][p2++];
22             }
23             for(int h=1;h<=k;h++) dp[j][h]=tmp[h];
24         }
25     for(int i=1;i<=k;i++) ans+=dp[v][i];
26     printf("%d",ans);
27     return 0;
28 } 
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/9770413.html