背包问题

背包问题

背包问题是使用dp的经典问题,本篇文章将讲解所有的背包问题,文章也会不断完善,不断通俗易懂。
背包问题是使用dp的经典问题,本篇文章将讲解所有的背包问题,文章也会不断完善,不断通俗易懂。
背包问题是使用dp的经典问题,本篇文章将讲解所有的背包问题,文章也会不断完善,不断通俗易懂。
背包问题是使用dp的经典问题,本篇文章将讲解所有的背包问题,文章也会不断完善,不断通俗易懂。

01背包

Acwing 2. 01背包问题
空间未优化版本

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int v[N], w[N], f[N][N];
int main(){
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++ ){
scanf("%d%d", &v[i], &w[i]);
}
for(int i = 1; i <= n; i ++ ){
for(int j = 1; j <= m; j ++ ){
if(j < v[i]) f[i][j] = f[i - 1][j];
else f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]);
}
}
printf("%d", f[n][m]);
return 0;
}

空间优化版本

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int v[N], w[N], f[N];
int main(){
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++ ){
scanf("%d%d", &v[i], &w[i]);
}
for(int i = 1; i <= n; i ++ ){
for(int j = m; j >= v[i]; j -- ){
f[j] = max(f[j], f[j - v[i]] + w[i]);
}
}
printf("%d", f[m]);
return 0;
}

完全背包

Acwing 3. 完全背包问题
空间未优化版本

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int v[N], w[N], f[N][N];
int main(){
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++ ){
scanf("%d%d", &v[i], &w[i]);
}
for(int i = 1; i <= n; i ++ ){
for(int j = 1; j <= m; j ++ ){
if(j < v[i]) f[i][j] = f[i - 1][j];
else f[i][j] = max(f[i - 1][j], f[i][j - v[i]] + w[i]);
}
}
printf("%d", f[n][m]);
return 0;
}

空间优化版本

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int v[N], w[N], f[N];
int main(){
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++ ){
scanf("%d%d", &v[i], &w[i]);
}
for(int i = 1; i <= n; i ++ ){
for(int j = v[i]; j <= m; j ++ ){
f[j] = max(f[j], f[j - v[i]] + w[i]);
}
}
printf("%d", f[m]);
return 0;
}

多重背包(TODO)

Acwing 多重背包问题 I

#include<bits/stdc++.h>
using namespace std;
const int N = 1e2 + 10;
int v[N], w[N], s[N], f[N][N];
int main(){
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++ ) scanf("%d%d%d", &v[i], &w[i], &s[i]);
for(int i = 1; i <= n; i ++ ){
for(int j = 1; j <= m; j ++ ){
for(int k = 0; k <= s[i] && j >= k * v[i]; k ++ ){
f[i][j] = max(f[i][j], f[i - 1][j - k * v[i]] + k * w[i]);
}
}
}
printf("%d", f[n][m]);
return 0;
}

空间优化版本

#include<bits/stdc++.h>
using namespace std;
const int N = 1e2 + 10;
int v[N], w[N], s[N], f[N];
int main(){
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++ ) scanf("%d%d%d", &v[i], &w[i], &s[i]);
for(int i = 1; i <= n; i ++ ){
for(int j = m; j >= v[i]; j -- ){
for(int k = 1; k <= s[i] && j >= k * v[i]; k ++ ){ // k 只取到1就可以了,因为f[j]代表了上一次循环的旧值和迭代1~s[i]的最大f[j]
f[j] = max(f[j], f[j - k * v[i]] + k * w[i]);
}
}
}
printf("%d", f[m]);
return 0;
}

二进制优化版本

#include<bits/stdc++.h>
using namespace std;
const int N = 2e4 + 10; // log(2000) * 1000 = 11000
int v[N], w[N], f[N][N], num;
int main(){
int n, m, vv, ww, s;
scanf("%d%d", &n, &m);
while(n -- ){
scanf("%d%d%d", &vv, &ww, &s);
for(int k = 1; k <= s; k <<= 1){
v[ ++ num] = k * vv;
w[num] = k * ww;
s -= k;
}
if(s){
v[ ++ num] = s * vv;
w[num] = s * ww;
}
}
for(int i = 1; i <= num; i ++ ){
for(int j = 1; j <= m; j ++ ){
if(j < v[i]) f[i][j] = f[i - 1][j];
else f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]);
}
}
printf("%d", f[num][m]);
return 0;
}

内存溢出 Memory Limit Exceeded

二进制优化版本,内存优化

#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 2000; // log(2000) * 1000 = 11000
int v[N], w[N], f[N], num;
int main(){
int n, m, vv, ww, s;
scanf("%d%d", &n, &m);
while(n -- ){
scanf("%d%d%d", &vv, &ww, &s);
for(int k = 1; k <= s; k <<= 1){
v[ ++ num] = k * vv;
w[num] = k * ww;
s -= k;
}
if(s){
v[ ++ num] = s * vv;
w[num] = s * ww;
}
}
for(int i = 1; i <= num; i ++ ){
for(int j = m; j >= v[i]; j -- ){
f[j] = max(f[j], f[j - v[i]] + w[i]);
}
}
printf("%d", f[m]);
return 0;
}

混合背包问题

Acwing 7. 混合背包问题
解法1

#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
int f[N], v[N], w[N], s[N], num;
int main(){
int n, m, vv, ww, ss;
scanf("%d%d", &n, &m);
while(n -- ){
scanf("%d%d%d", &vv, &ww, &ss);
if(ss == 0){
v[ ++ num] = vv;
w[num] = ww;
s[num] = 0; // 完全背包
}else{
if(ss == -1) ss = 1; // 01 按照 特殊多重背包处理,统一转01背包
for(int k = 1; k <= ss; k <<= 1){
v[ ++ num] = k * vv;
w[num] = k * ww;
s[num] = 1; // 01背包
ss -= k;
}
if(ss){
v[ ++ num] = ss * vv;
w[num] = ss * ww;
s[num] = 1; // 01背包
}
}
}
for(int i = 1; i <= num; i ++ ){
if(s[i] == 1){ // 01 背包
for(int j = m; j >= v[i]; j -- ){
f[j] = max(f[j], f[j - v[i]] + w[i]);
}
}else{ // 完全背包
for(int j = v[i]; j <= m; j ++ ){
f[j] = max(f[j], f[j - v[i]] + w[i]);
}
}
}
printf("%d", f[m]);
return 0;
}

解法二

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int f[N], g[N], q[N], h, t;
int n, m;
void zero_one_pack(int v, int w){
for(int j = m; j >= v; j -- ) f[j] = max(f[j], f[j - v] + w);
}
void complete_pack(int v, int w){
for(int j = v; j <= m; j ++ ) f[j] = max(f[j], f[j - v] + w);
}
void multiple_pack(int v, int w, int s){
memcpy(g, f, sizeof f);
for(int j = 0; j < v; j ++ ){
h = 0, t = -1;
for(int k = j; k <= m; k += v){
while(h <= t && g[k] >= g[q[t]] + (k - q[t]) / v * w) t -- ;
q[ ++ t] = k;
if(h <= t && q[h] < k - s * v) h ++ ;
f[k] = g[q[h]] + (k - q[h]) / v * w;
}
}
}
int main(){
int v, w, s;
scanf("%d%d", &n, &m);
while(n -- ){
scanf("%d%d%d", &v, &w, &s);
if(s == -1) zero_one_pack(v, w); // 01背包
else if(s == 0) complete_pack(v, w); // 完全背包
else multiple_pack(v, w, s); // 多重背包
}
printf("%d", f[m]);
return 0;
}

二维费用背包

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int f[N][N];
int main(){
int N, V, M, v, m, w;
scanf("%d%d%d", &N, &V, &M);
while(N -- ){
scanf("%d%d%d", &v, &m, &w); // 体积、重量、价值
for(int j = V; j >= v; j -- ){
for(int k = M; k >= m; k -- ){
f[j][k] = max(f[j][k], f[j - v][k - m] + w);
}
}
}
printf("%d", f[V][M]);
return 0;
}

分组背包

TODO

本文作者:爱情丶眨眼而去

本文链接:https://www.cnblogs.com/zshsboke/p/17860226.html

版权声明:本作品采用©️CC BY-NC-SA 4.0许可协议进行许可。

posted @   爱情丶眨眼而去  阅读(37)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
🔑
  1. 1 赤伶 HITA
  2. 2 樱花树下的约定 (DJ-lucky小阳版) 旺仔小乔
  3. 3 踏雪 国风新语,Babystop_山竹
  4. 4 虞兮叹 闻人听書_
  5. 5 广寒宫 花沫
  6. 6 踏山河 七叔(叶泽浩)
  7. 7 破茧 张韶涵
  8. 8 下山 要不要买菜
  9. 9 红昭愿 音阙诗听
  10. 10 渡我不渡她 独孤
  11. 11 海草舞 陈冬霖
  12. 12 纸短情长 (女声版) 林玉冰
  13. 13 把梦照亮 赵小炮
  14. 14 沙漠骆驼 烟火兄弟
  15. 15 赢在江湖 姜鹏
  16. 16 孤勇者 杨宇峰
  17. 17 口是心非 张大帅
  18. 18 赐我 小时姑娘
  19. 19 囍(Chinese Wedding) 葛东琪
虞兮叹 - 闻人听書_
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

虞兮叹 - 闻人听書_

词 Lyrics:祝何

曲 Music:祝何

编曲 Arranger:祝何

混音师 Mixing Engineer:唐瑜

和声 Backing vocals:田跃君

制作人 Produced by:蒋雪儿 Snow.J

监制 Executive producer:蒋雪儿 Snow.J

OP:青风音乐Cheerful Music

SP:青风音乐Cheerful Music

(未经授权不得翻唱或使用)

楚河流沙几聚散

日月沧桑尽变换

乱世多少红颜换一声长叹

谁曾巨鹿踏破了秦关

千里兵戈血染

终究也不过是风轻云淡

长枪策马平天下

此番诀别却为难

一声虞兮虞兮泪眼已潸然

与君共饮这杯中冷暖

西风彻夜回忆吹不断

醉里挑灯看剑 妾舞阑珊

垓下一曲离乱 楚歌声四方

含悲 辞君 饮剑 血落凝寒霜

难舍一段过往 缘尽又何妨

与你魂归之处便是苍茫

长枪策马平天下

长枪策马平天下

此番诀别却为难

一声虞兮虞兮泪眼已潸然

与君共饮这杯中冷暖

西风彻夜回忆吹不断

醉里挑灯看剑 妾舞阑珊

垓下一曲离乱 楚歌声四方

含悲 辞君 饮剑 血落凝寒霜

难舍一段过往 缘尽又何妨

与你魂归之处便是苍茫

汉兵刀剑纷乱 折断了月光

江畔 只身 孤舟 余生不思量

难舍一段过往 缘尽又何妨

与你来生共寄山高水长