第K大01背包
其实这个问题,真的挺好想的,但是我咋想了那么久呢~~
很好理解,第K大01背包一定基于01背包,dp数组也很容易的想到由dp[V] ----> dp[V][K],来表示背包容量是V时候的第K大背包
然后就是状态转移方程了,多写一写,你也能手推出来的,不能被吓到
dp[V][1] = max_第一大(dp[v][1],dp[v-w][1]+vi)
dp[V][2] = max_第二大数(dp[v][1],dp[v-w][1]+vi,dp[v][2],dp[v-w][2]+vi) = max_第二大数(dp[v][1],dp[v][2],dp[v-w][2]+vi)
从而得到一般式子
dp[v][k] = max_第K大(dp[v][1],dp[v][2],....dp[v][k],dp[v-w][1]+vi,.....dp[v-w][k]+vi
明白了这两个,代码方面就比较好实现了
可以用排序来进行
但是一看排列,发现取第K大值分为两部分,且排列都是降序,所以我们可以用两个数组存储起来,然后进行赋值(复杂度也比较低)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | /* dp[x][y]表示的是容量为x的第k大值 所以dp[x][1] = max_(第一大值){dp[x][1],dp[x-v][1]+w} dp[x][2] = max_(第二大值){dp[x][1],dp[x][2],dp[x-v][1]+w,dp[x-v][2]+w} 依次类推~~ */ /* 因为dp[j][1]...dp[j][k]与dp[j-w[i]][1]+v[i]...dp[j-w[i]][k]+v[i] 是依次递减的,那么我们可以用两个数组将这两组数组保存起来, 再O(N)的时间内求得第K大。 */ #include <iostream> #include <cstdio> #include <string.h> #include <algorithm> #include <cmath> using namespace std; const int maxn = 1005; int dp[maxn][maxn]; int n,W,K; //W:总容量值,K第K大值 int v[maxn],w[maxn]; //价值,一个为体积 int s1[maxn],s2[maxn]; void KthZeroOnePack() { for ( int i = 0;i < n;i++) //遍历了每一个物品 { for ( int j = W;j >= w[i];j--) //层铺每一层体积 { for ( int th = 1;th <= K;th++) //求取前k大值 { //0 - k-1 到K结束 s1[th-1] = dp[j][th]; //遍历存储每一个可能取到的值,且s1是递减的 s2[th-1] = dp[j - w[i]][th] + v[i]; //遍历存储每一个可能取到的值,且s2是递减的 } //特判结束点 s1[K] = s2[K] = -1; int cnt = 1,cnt1 = 0,cnt2 = 0; //从第一大开始 while (cnt <= K && (s1[cnt1] != -1 || s2[cnt2] != -1)) { if (s1[cnt1] > s2[cnt2])dp[j][cnt] = s1[cnt1++]; else dp[j][cnt] = s2[cnt2++]; //严格递减 if (dp[j][cnt] != dp[j][cnt-1]) cnt++; } } } } int main() { int T; scanf( "%d" ,&T); while (T--) { scanf( "%d%d%d" ,&n,&W,&K); memset(dp,0, sizeof (dp)); for ( int i = 0;i < n;i++) { scanf( "%d" ,&v[i]); } for ( int i = 0;i < n;i++) { scanf( "%d" ,&w[i]); } KthZeroOnePack(); printf( "%d\n" ,dp[W][K]); } return 0; } |
__EOF__

本文作者:YiMeng
本文链接:https://www.cnblogs.com/DF-yimeng/p/9334875.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/DF-yimeng/p/9334875.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律