zoukankan      html  css  js  c++  java
  • 背包问题整理

    一:01背包

    有 NN 件物品和一个容量是 VV 的背包。每件物品只能使用一次。

    第 ii 件物品的体积是 vivi,价值是 wiwi。

    求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
    输出最大价值。

    输入格式

    第一行两个整数,NVN,V,用空格隔开,分别表示物品数量和背包容积。

    接下来有 NN 行,每行两个整数 vi,wivi,wi,用空格隔开,分别表示第 ii 件物品的体积和价值。

    输出格式

    输出一个整数,表示最大价值。

    数据范围

    0<N,V10000<N,V≤1000
    0<vi,wi10000<vi,wi≤1000

    输入样例

    4 5
    1 2
    2 4
    3 4
    4 5
    

    输出样例:

    8

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int N = 1010;
     5 
     6 int a[N], b[N];
     7 //int dp[N];
     8 int n, v;
     9 
    10 vector<vector<int>> memo(N, vector<int>(N, -1));
    11 
    12 int dfs(int i, int j){
    13     if(memo[i][j] != -1) return memo[i][j];
    14     if(i == 0) return memo[i][j] = 0;
    15     int dfs1 = dfs(i-1, j);
    16     int dfs2 = -1;
    17     if(j >= a[i]) dfs2 = dfs(i-1, j - a[i]) + b[i];
    18     return memo[i][j] = max(dfs1, dfs2);
    19 }
    20 
    21 int main(){
    22     cin >> n >> v;
    23     for(int i = 1;i <= n;++i) cin >> a[i] >> b[i];//v p
    24     /*
    25     for(int i = 1;i <= n;++i)
    26         for(int j = v;j >= a[i];--j)
    27             dp[j] = max(dp[j], dp[j-a[i]] + b[i]);//核心,第i层状态由第i-1层状态得到
    28     */    
    29     cout << dfs(n, v) << endl;
    30     return 0;    
    31 }
    View Code

    二:完全背包

    有 NN 种物品和一个容量是 VV 的背包,每种物品都有无限件可用。

    第 ii 种物品的体积是 vivi,价值是 wiwi。

    求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
    输出最大价值。

    输入格式

    第一行两个整数,NVN,V,用空格隔开,分别表示物品种数和背包容积。

    接下来有 NN 行,每行两个整数 vi,wivi,wi,用空格隔开,分别表示第 ii 种物品的体积和价值。

    输出格式

    输出一个整数,表示最大价值。

    数据范围

    0<N,V10000<N,V≤1000
    0<vi,wi10000<vi,wi≤1000

    输入样例

    4 5
    1 2
    2 4
    3 4
    4 5
    

    输出样例:

    10


     1 #include <iostream>
     2 using namespace std;
     3 
     4 const int N = 1010;
     5 
     6 int dp[N];
     7 int n, v;
     8 
     9 int w[N], p[N];
    10 
    11 int main(){
    12     cin >> n >> v;
    13     for(int i = 1;i <= n;++i) cin >> w[i] >> p[i];
    14 
    15     for(int i = 1;i <= n;++i)
    16         for(int j = w[i];j <= v;++j)
    17             //max后的dp[j]表示的是第i-1层的值,dp[j-w[i]]表示的是当前第i层如果要选k个物品由选k-1个物品更新得到
    18             dp[j] = max(dp[j], dp[j-w[i]] + p[i]);
    19     cout << dp[v] << endl;
    20     return 0;
    21 }
    View Code

    三:多重背包(未优化)

    有 NN 种物品和一个容量是 VV 的背包。

    第 ii 种物品最多有 sisi 件,每件体积是 vivi,价值是 wiwi。

    求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
    输出最大价值。

    输入格式

    第一行两个整数,NVN,V,用空格隔开,分别表示物品种数和背包容积。

    接下来有 NN 行,每行三个整数 vi,wi,sivi,wi,si,用空格隔开,分别表示第 ii 种物品的体积、价值和数量。

    输出格式

    输出一个整数,表示最大价值。

    数据范围

    0<N,V1000<N,V≤100
    0<vi,wi,si1000<vi,wi,si≤100

    输入样例

    4 5
    1 2 3
    2 4 1
    3 4 3
    4 5 2
    

    输出样例:

    10


     1 #include <iostream>
     2 using namespace std;
     3 
     4 const int N = 1010;
     5 
     6 int dp[N];
     7 int n, v;
     8 
     9 int w[N], p[N], s[N];
    10 
    11 int main(){
    12     cin >> n >> v;
    13     for(int i = 1;i <= n;++i) cin >> w[i] >> p[i] >> s[i];
    14     
    15     for(int i = 1;i <= n;++i){
    16         for(int j = v;j >= 0;--j){
    17             int t = 0;
    18             while(t <= s[i] && j >= t * w[i]){
    19                 dp[j] = max(dp[j], dp[j - t*w[i]] +  t*p[i]);
    20                 ++t;
    21             }
    22         }
    23     }
    24                 
    25     cout << dp[v] << endl;
    26     return 0;
    27 }
    View Code

    四:多重背包(二进制优化)

     1 #include <iostream>
     2 using namespace std;
     3 
     4 const int N = 1000*2000;
     5 
     6 int n, v;
     7 int dp[N], w[N], p[N];
     8 
     9 int main(){
    10     cin >> n >> v;
    11     //拆分
    12     int cnt = 0;
    13     for(int i = 1;i <= n;++i){
    14         int a, b, sum; cin >> a >> b >> sum;
    15         int k = 1;
    16         while(k <= sum){
    17             ++cnt;
    18             w[cnt] = a*k;
    19             p[cnt] = b*k;
    20             sum -= k;
    21             k *= 2;
    22         }
    23         if(sum){
    24             ++cnt;
    25             w[cnt] = a*sum;
    26             p[cnt] = b*sum;
    27         }
    28     }    
    29     //按照01背包问题求解
    30     for(int i = 1;i <= cnt;++i)
    31         for(int j = v;j >= w[i];--j)
    32             dp[j] = max(dp[j], dp[j-w[i]]+p[i]);
    33     
    34     cout << dp[v] << endl;
    35     return 0;
    36 }
    View Code

    五:分组背包:

    有 NN 组物品和一个容量是 VV 的背包。

    每组物品有若干个,同一组内的物品最多只能选一个。
    每件物品的体积是 vijvij,价值是 wijwij,其中 ii 是组号,jj 是组内编号。

    求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。

    输出最大价值。

    输入格式

    第一行有两个整数 NVN,V,用空格隔开,分别表示物品组数和背包容量。

    接下来有 NN 组数据:

    • 每组数据第一行有一个整数 SiSi,表示第 ii 个物品组的物品数量;
    • 每组数据接下来有 SiSi 行,每行有两个整数 vij,wijvij,wij,用空格隔开,分别表示第 ii 个物品组的第 jj 个物品的体积和价值;

    输出格式

    输出一个整数,表示最大价值。

    数据范围

    0<N,V1000<N,V≤100
    0<Si1000<Si≤100
    0<vij,wij1000<vij,wij≤100

    输入样例

    3 5
    2
    1 2
    2 4
    1
    3 4
    1
    4 5
    

    输出样例:

    8

     1 #include <iostream>
     2 using namespace std;
     3 
     4 const int N = 110;
     5 int v[N][N], w[N][N];
     6 int s[N];
     7 int dp[N];
     8 
     9 int main(){
    10     int n, m; cin >> n >> m;
    11     for(int i = 1;i <= n;++i){
    12         cin >> s[i];       
    13         for(int j = 1;j <= s[i];++j)
    14             cin >> v[i][j] >> w[i][j];
    15     }
    16     
    17     for(int i = 1;i <= n;++i)
    18         for(int j = m;j >= 0;--j)
    19             for(int k = 1;k <= s[i];++k)
    20                 if(j >= v[i][k])
    21                     dp[j] = max(dp[j], dp[j - v[i][k]] + w[i][k]);
    22     
    23     cout << dp[m] << endl;
    24     return 0;
    25 }
    View Code

    end

  • 相关阅读:
    Redis主从复制
    Redis发布订阅
    Redis持久化
    初探redis.config
    java连接Linux服务器问题
    Redis常见类型及API
    Redis安装
    Nosql
    JMM
    SpringSecurity
  • 原文地址:https://www.cnblogs.com/sxq-study/p/12298739.html
Copyright © 2011-2022 走看看