c/c++藍橋杯經典編程題100道(21)背包問題

背包問題

->返回c/c++藍橋杯經典編程題100道-目錄


目錄

背包問題

一、題型解釋

二、例題問題描述

三、C語言實現

解法1:0-1背包(基礎動態規劃,難度★)

解法2:0-1背包(空間優化版,難度★★)

解法3:完全背包(難度★★)

四、C++實現

解法1:0-1背包(STL vector版,難度★☆)

解法2:多重背包(二進制優化,難度★★★)

五、總結對比表

六、特殊方法與內置函數補充

1. C++ STL的?max?函數

2. 滾動數組優化

3. 單調隊列優化


一、題型解釋

背包問題是動態規劃中的經典問題,核心是?在限定容量下選擇物品使得總價值最大化。常見變種:

  1. 0-1背包:每個物品只能選或不選(每個物品1個)。

  2. 完全背包:每個物品可以選無限次。

  3. 多重背包:每個物品最多選指定次數。

  4. 分組背包:每組物品中只能選一個。


二、例題問題描述

例題1(0-1背包)

  • 容量?W=4,物品重量?[1,3,4],價值?[15,20,30],輸出最大價值?35(選物品0和2)。

例題2(完全背包)

  • 容量?W=5,物品重量?[1,2],價值?[15,20],輸出最大價值?75(選5個物品0)。

例題3(多重背包)

  • 容量?W=10,物品重量?[2,3],價值?[5,7],數量?[2,3],輸出最大價值?24(選3個物品1)。

例題4(分組背包)

  • 容量?W=6,分組物品?[[1,2], [3,4]](每組選一個),輸出最大價值?6(選第一組2,第二組4)。


三、C語言實現

解法1:0-1背包(基礎動態規劃,難度★)

通俗解釋

  • 填表格記錄不同容量下的最大價值,像存錢罐一樣逐步塞入物品。

c

#include <stdio.h>
#include <string.h>#define MAX_W 100
#define MAX_N 100int max(int a, int b) { return a > b ? a : b; }int knapsack01(int W, int wt[], int val[], int n) {int dp[MAX_N][MAX_W]; // dp[i][j]:前i個物品,容量j的最大價值memset(dp, 0, sizeof(dp));for (int i = 1; i <= n; i++) {for (int j = 1; j <= W; j++) {if (wt[i-1] > j) { // 當前物品超重,無法選擇dp[i][j] = dp[i-1][j];} else { // 能選:比較選或不選的價值dp[i][j] = max(dp[i-1][j], dp[i-1][j - wt[i-1]] + val[i-1]);}}}return dp[n][W];
}int main() {int W = 4;int wt[] = {1,3,4}, val[] = {15,20,30};int n = sizeof(wt)/sizeof(wt[0]);printf("0-1背包最大價值:%d\n", knapsack01(W, wt, val, n)); // 輸出35return 0;
}

代碼邏輯

  1. 初始化DP表dp[i][j]?表示前?i?個物品在容量?j?下的最大價值。

  2. 填表規則

    • 物品超重時,繼承上一行結果。

    • 否則,取“不選”和“選”的最大值。


解法2:0-1背包(空間優化版,難度★★)

通俗解釋

  • 僅用一維數組,倒序遍歷容量,避免覆蓋未計算的數據。

c

int knapsack01Optimized(int W, int wt[], int val[], int n) {int dp[MAX_W] = {0};for (int i = 0; i < n; i++) { // 遍歷物品for (int j = W; j >= wt[i]; j--) { // 逆序更新,防止重復選dp[j] = max(dp[j], dp[j - wt[i]] + val[i]);}}return dp[W];
}

代碼邏輯

  1. 一維數組dp[j]?表示容量?j?的最大價值。

  2. 逆序遍歷:確保每個物品只被選一次。


解法3:完全背包(難度★★)

通俗解釋

  • 正序遍歷容量,允許重復選擇物品,像存錢罐可以多次塞硬幣。

c

int completeKnapsack(int W, int wt[], int val[], int n) {int dp[MAX_W] = {0};for (int i = 0; i < n; i++) {for (int j = wt[i]; j <= W; j++) { // 正序更新,允許重復選dp[j] = max(dp[j], dp[j - wt[i]] + val[i]);}}return dp[W];
}int main() {int W = 5;int wt[] = {1,2}, val[] = {15,20};int n = sizeof(wt)/sizeof(wt[0]);printf("完全背包最大價值:%d\n", completeKnapsack(W, wt, val, n)); // 輸出75return 0;
}

代碼邏輯

  • 正序遍歷:允許同一物品多次被選中。


四、C++實現

解法1:0-1背包(STL vector版,難度★☆)

通俗解釋

  • 使用?vector?替代數組,動態管理內存,避免固定大小限制。

cpp

#include <iostream>
#include <vector>
using namespace std;int knapsack01STL(int W, vector<int>& wt, vector<int>& val) {vector<int> dp(W + 1, 0);for (int i = 0; i < wt.size(); i++) {for (int j = W; j >= wt[i]; j--) { // 逆序更新dp[j] = max(dp[j], dp[j - wt[i]] + val[i]);}}return dp[W];
}int main() {vector<int> wt = {1,3,4}, val = {15,20,30};int W = 4;cout << "0-1背包最大價值:" << knapsack01STL(W, wt, val) << endl; // 輸出35return 0;
}

代碼邏輯

  • 與C語言空間優化版相同,但使用?vector?動態管理內存。


解法2:多重背包(二進制優化,難度★★★)

通俗解釋

  • 將物品數量拆分為二進制組合(如7=1+2+4),轉化為0-1背包問題。

cpp

int multiKnapsack(int W, vector<int>& wt, vector<int>& val, vector<int>& cnt) {vector<int> dp(W + 1, 0);for (int i = 0; i < wt.size(); i++) {int k = 1;int remain = cnt[i];while (k <= remain) { // 二進制拆分int w = wt[i] * k;int v = val[i] * k;for (int j = W; j >= w; j--) {dp[j] = max(dp[j], dp[j - w] + v);}remain -= k;k *= 2;}if (remain > 0) { // 處理剩余數量int w = wt[i] * remain;int v = val[i] * remain;for (int j = W; j >= w; j--) {dp[j] = max(dp[j], dp[j - w] + v);}}}return dp[W];
}int main() {vector<int> wt = {2,3}, val = {5,7}, cnt = {2,3};int W = 10;cout << "多重背包最大價值:" << multiKnapsack(W, wt, val, cnt) << endl; // 輸出24return 0;
}

代碼邏輯

  1. 二進制拆分:將數量拆分為2的冪次之和,減少物品數量。

  2. 轉化為0-1背包:對每個拆分后的物品進行0-1背包處理。


五、總結對比表

方法時間復雜度空間復雜度優點缺點
0-1背包基礎DPO(nW)O(nW)直觀易理解內存占用高
0-1背包空間優化O(nW)O(W)內存高效無法回溯具體方案
完全背包O(nW)O(W)支持無限次選擇不適用0-1場景
多重背包優化O(nW logS)O(W)處理數量限制實現較復雜

六、特殊方法與內置函數補充

1. C++ STL的?max?函數

  • 用法max(a, b)?返回較大值,需包含?<algorithm>?頭文件。

2. 滾動數組優化

  • 原理:利用奇偶行交替存儲,將二維DP壓縮為兩個一維數組。

3. 單調隊列優化

  • 適用場景:多重背包的進一步優化,時間復雜度降至O(nW)。

->返回c/c++藍橋杯經典編程題100道-目錄

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/895338.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/895338.shtml
英文地址,請注明出處:http://en.pswp.cn/news/895338.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

講解下MySql的外連接查詢在SpringBoot中的使用情況

在Spring Boot中使用MySQL的外連接查詢時&#xff0c;通常通過JPA、MyBatis或JDBC等持久層框架來實現。外連接查詢主要用于從多個表中獲取數據&#xff0c;即使某些表中沒有匹配的記錄。外連接分為左外連接&#xff08;LEFT JOIN&#xff09;、右外連接&#xff08;RIGHT JOIN&…

【大模型知識點】什么是KV Cache?為什么要使用KV Cache?使用KV Cache會帶來什么問題?

1.什么是KV Cache&#xff1f;為什么要使用KV Cache&#xff1f; 理解此問題&#xff0c;首先需理解自注意機制的計算和掩碼自注意力機制&#xff0c;在Decoder架構的模型中&#xff0c;每生成一個新的token&#xff0c;便需要重新執行一次自注意力計算&#xff0c;這個過程中…

【STM32】HAL庫Host MSC讀寫外部U盤及FatFS文件系統的USB Disk模式

【STM32】HAL庫Host MSC讀寫外部U盤及FatFS文件系統的USB Disk模式 在先前 分別介紹了FatFS文件系統和USB虛擬U盤MSC配置 前者通過MCU讀寫Flash建立文件系統 后者通過MSC連接電腦使其能夠被操作 這兩者可以合起來 就能夠實現同時在MCU、USB中操作Flash的文件系統 【STM32】通過…

1.1計算機的發展

一、計算機系統的概念 1、計算機系統軟件&#xff0b;硬件 軟件&#xff1a;由具有各種特殊功能的程序組成。 硬件&#xff1a;計算機的實體。如&#xff1a;主機、外設等。 硬件決定了計算機系統的上限&#xff0c;軟件決定了硬件性能發揮了多少。 2、軟件 軟件有系統軟…

本地生活服務平臺開發進入發展熱潮

本地生活服務平臺&#xff1a;當下的發展熱潮 本地生活服務平臺開發模式 在當今數字化時代&#xff0c;本地生活服務平臺開發已成為人們日常生活中不可或缺的一部分。只需動動手指&#xff0c;打開手機上的 APP&#xff0c;就能輕松滿足各類生活需求。像某團、餓XX這樣的平臺&a…

LSTM變種模型

GRU GRU簡介 門控循環神經網絡 (Gated Recurrent Neural Network&#xff0c;GRNN) 的提出&#xff0c;旨在更好地捕捉時間序列中時間步距離較大的依賴關系。它通過可學習的門來控制信息的流動。其中&#xff0c;門控循環單元 (Gated Recurrent Unit &#xff0c; GRU) 是…

詳解tensorflow的tensor和Python list及Numpy矩陣的區別

TensorFlow中的張量&#xff08;tensor&#xff09;、Python列表和NumPy矩陣在數據結構和功能上有一些顯著的區別。以下是它們的詳細介紹及代碼示例。 1、Python List 定義&#xff1a;Python列表是一種內置的數據結構&#xff0c;可以存儲不同類型的對象&#xff0c;包括數字…

多模態模型詳解

多模態模型是什么 多模態模型是一種能夠處理和理解多種數據類型&#xff08;如文本、圖像、音頻、視頻等&#xff09;的機器學習模型&#xff0c;通過融合不同模態的信息來提升任務的性能。其核心在于利用不同模態之間的互補性&#xff0c;增強模型的魯棒性和準確性。 如何融合…

微服務與網關

什么是網關 背景 單體項目中&#xff0c;前端只用訪問指定的一個端口8080&#xff0c;就可以得到任何想要的數據 微服務項目中&#xff0c;ip是不斷變化的&#xff0c;端口是多個的 解決方案&#xff1a;網關 網關&#xff1a;就是網絡的關口&#xff0c;負責請求的路由、轉發…

二分算法篇:二分答案法的巧妙應用

二分算法篇&#xff1a;二分答案法的巧妙應用 那么看到二分這兩個字想必我們一定非常熟悉&#xff0c;那么在大學期間的c語言的教學中會專門講解二分查找&#xff0c;那么我們來簡單回顧一下二分查找算法&#xff0c;我們知道二分查找是在一個有序的序列中尋找一個數在這個序列…

XZ_Mac電腦上本地化部署DeepSeek的詳細步驟

根據您的需求&#xff0c;以下是Mac電腦上本地化部署DeepSeek的詳細步驟&#xff1a; 一、下載并安裝Ollama 訪問Ollama官網&#xff1a; 打開瀏覽器&#xff0c;訪問 Ollama官網。 下載Ollama&#xff1a; 在官網中找到并點擊“Download”按鈕&#xff0c;選擇適合Mac系統的…

C# OpenCV機器視覺:模仿Halcon各向異性擴散濾波

在一個充滿創意與挑戰的圖像處理工作室里&#xff0c;阿強是一位熱情的圖像魔法師。他總是在追求更加出色的圖像效果&#xff0c;然而&#xff0c;傳統的圖像處理方法有時候并不能滿足他的需求。 有一天&#xff0c;阿強聽說了 Halcon 中的各向異性擴散濾波功能&#xff0c;它…

實現:多活的基礎中間件

APIRouter &#xff1a; 路由分發服務 API Router 是一個 HTTP 反向代理和負載均衡器&#xff0c;部署在公有云中作為 HTTP API 流量的入口&#xff0c;它能識別 出流量的歸屬 shard &#xff0c;并根據 shard 將流量轉發到對應的 ezone 。 API Router 支持多種路由鍵&am…

Python3連接MongoDB并寫入數據

個人博客地址&#xff1a;Python3連接MongoDB并寫入數據 | 一張假鈔的真實世界 安裝PyMongo $ pip3 install pymongo Successfully installed pymongo-3.7.2 連接MongoDB并且批量插入操作 #!/usr/bin/python3import mysql.connector import gzip import json from pymongo …

Python 操作 MongoDB 教程

一、引言 在當今數字化時代&#xff0c;數據的存儲和管理至關重要。傳統的關系型數據庫在處理一些復雜場景時可能會顯得力不從心&#xff0c;而 NoSQL 數據庫應運而生。MongoDB 作為一款開源的、面向文檔的 NoSQL 數據庫&#xff0c;憑借其高性能、高可擴展性和靈活的數據模型…

使用 Python-pptx 庫提取 PPTX 文件中的結構與文字

是的&#xff0c;使用 python-pptx 庫是提取 PPTX 文件中結構和文字的理想選擇&#xff0c;原因如下&#xff1a; 專門處理 PPTX 格式 python-pptx 是一個專門為處理 PPTX 文件&#xff08;.pptx 格式&#xff09;而設計的 Python 庫。 它可以讀取和操作 PPTX 文件的內部結構…

DeepSeek本地化部署

DeepSeek本地化部署 本教程為一鍵式部署&#xff0c;適合于mac、ubuntu、windows。【開源地址】 環境要求 nodejs > 18Python > 3.10.12 步驟一&#xff1a;安裝ollama客戶端 官網直接安裝&#xff0c;ollama官網。安裝完成后使用命令&#xff1a;ollama -h&#xf…

驅動開發系列34 - Linux Graphics Intel 動態顯存技術的實現

一:概述 動態顯存技術(Dynamic Video Memory Technology, DVMT)是一種由 Intel 提出的內存分配技術,主要用于整合顯卡(集成顯卡)系統中,以便動態地調整顯存大小,從而在不同的負載場景下優化內存使用和系統性能。 動態顯存技術的核心在于共享系統內存。集成顯卡沒有獨立…

DeepSeek 入駐 Cursor —— 表現能否超越 Claude?

DeepSeek 剛剛在 Cursor 平臺上線了它的兩款模型&#xff1a;DeepSeek V3 和 R1。目前&#xff0c;許多開發者&#xff08;包括我們在內&#xff09;主要依賴 Claude 3.5 Sonnet&#xff08;最新版本 claude-3-5-sonnet-20241022&#xff09;作為主要語言模型&#xff0c;因此我…

持久性HTTPVS.非持久性HTTP

1. HTTP協議基礎 HTTP&#xff08;HyperText Transfer Protocol&#xff09;是Web通信的核心協議&#xff0c;定義了客戶端&#xff08;瀏覽器&#xff09;與服務器之間傳輸數據的規則。 在HTTP/1.0及之前的版本中&#xff0c;默認使用非持久性連接&#xff0c;而HTTP/1.1及更…