求01背包前k优解的价值和(题面还挺亲切的)
本来我想的是直接边跑01背包边记录,最后排序...
然后意识到,这种方法是枚举不全的。
看了眼题解...要多开一维!
k的范围很小,f[i][j]表示空间为i,是第j优解。
那么,因为有许多j,所以对于每个不一样的j,
f[i][j]既可能从f[i-c][...]+w转移过来,也可能从f[i][...]转移过来。
用类似于归并排序的方法:
维护两个指针t1,t2;
同时为了防止新的f覆盖原来的影响后续的状态转移,用一个临时的g[]记录,最后再转移过去。
那么就有g[t] = max(f[j-c][t1++]+w,f[j][t2++])
最后答案统计f[m][1-k]就可以了。
代码如下
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #define MogeKo qwq #define Darcy amour using namespace std; const int maxn = 1e5+10; const int INF = 0x3f3f3f3f; int k,m,n,c,w,ans,f[maxn][60],g[60]; int main() { scanf("%d%d%d",&k,&m,&n); memset(f,-INF,sizeof(f)); f[0][1] = 0; for(int i = 1; i <= n; i++) { scanf("%d%d",&c,&w); for(int j = m; j >= c; j--) { int t1 = 1,t2 = 1; for(int t = 1; t <= k; t++) { if(f[j-c][t1] + w > f[j][t2]) g[t] = f[j-c][t1++] + w; else g[t] = f[j][t2++]; } for(int t = 1; t <= k; t++) f[j][t] = g[t]; } } for(int i = 1; i <= k; i++) ans += f[m][i]; printf("%d",ans); return 0; }
原文地址:https://www.cnblogs.com/mogeko/p/11715703.html
时间: 2024-09-30 15:58:46