zoukankan      html  css  js  c++  java
  • 【Luogu】【关卡2-15】动态规划的背包问题(2017年10月)【还差一道题】

    任务说明:这是最基础的动态规划。不过如果是第一次接触会有些难以理解。加油闯过这个坎。

    01背包二维数组优化成滚动数组的时候有坑有坑有坑!!!必须要downto,downto,downto

    情景和代码见装箱问题。

    P1060 开心的金明

    小明的妈妈给小明N元钱,小明想买m件物品,每个物品价值为 价格*重要度,求出不超过N元钱的情况下,最多能买多少价值的物品,输出价值。

    解法:直接的01背包问题,我居然还去看了书。。递推方程一次写不出来。方程需要记忆。

    dp[i][j]表示前i件物品总价格不超过j元的最大总价值。

    需要学习下怎么在博客园输入latex公式orz。。。

    #include <iostream>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    
    int main() {
        int n, m;
        cin >> n >> m;
        int w[m][2];
        for (int i = 0; i < m; ++i) {
            cin >> w[i][0] >> w[i][1];
            w[i][1] *= w[i][0];
        }
    
        int dp[m+1][n+1];
        memset(dp, 0, sizeof(dp));
    
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (w[i-1][0] > j) { dp[i][j] = dp[i-1][j]; }
                else {
                    dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i-1][0]] + w[i-1][1]);
                }
            }
        }
        cout << dp[m][n] << endl;
    
        return 0;
    }
    View Code

    P1164 小A点菜

    有M元, N种菜(每个菜只有一份),每种菜有价格,求能把M元全花完的方案数。

    解答:一开始全WA....哭死..其实还是经典的01背包问题。

    一维的转移方程为: dp[j] += dp[j-price[i-1]]; 初始化条件为 dp[0] = 1, dp[1..m] = 0。 (因为需要花0元只有一种方案,就是啥也不买)

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 int main() {
     5     int n, m;
     6     cin >> n >> m;
     7     int dp[m+1] = {0};
     8     dp[0] = 1;
     9     int price[n];
    10     for (int i = 0; i < n; ++i) {
    11         cin >> price[i];
    12     }
    13     for(int i = 1; i <= n; ++i) {
    14         for (int j = m; j >= 0; --j) {
    15             if (j >= price[i-1]) {
    16                 dp[j] = dp[j] + dp[j-price[i-1]];
    17             }
    18         }
    19     }
    20     cout << dp[m] << endl;
    21     return 0;
    22 }
    View Code

    金明的预算方案

    P1048 采药

    就是01背包,裸的,直接写了,方程同P1060

    提交一次AC

     1 #include <cstdlib>
     2 #include <cstdio>
     3 #include <iostream>
     4 #include <cstring>
     5 using namespace std;
     6 
     7 int main() {
     8     int T, M;
     9     cin >> T >> M;
    10     int w[M][2];
    11     for (int i = 0; i < M; ++i) {
    12         cin >> w[i][0] >> w[i][1];
    13     }
    14     int dp[M+1][T+1];
    15     memset(dp, 0, sizeof(dp));
    16 
    17     for (int i = 1; i <= M; ++i) {
    18         for (int j = 1; j <= T; ++j) {
    19             if (j < w[i-1][0]) { dp[i][j] = dp[i-1][j]; }
    20             else {
    21                 dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i-1][0]] + w[i-1][1]);
    22             }
    23         }
    24     }
    25     cout << dp[M][T] << endl;
    26     return 0;
    27 }
    View Code

    P1049 装箱问题

    有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30,每个物品有一个体积(正整数)。 要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

    就是求怎么样是用的空间最大。裸的01背包。优化成滚动数组的时候被坑了。

    //写成滚动数组的时候,max(dp[j], dp[j-w[i-1]]+w[i-1]);如果是从左到右,那么dp[j-w[i-1]]是个已经被更新过的值。。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 
     6 using namespace std;
     7 
     8 int main() {
     9     int c, n;
    10     cin >> c >> n;
    11     int w[n+1];
    12     for (int i = 0; i < n; ++i) {
    13         cin >> w[i];
    14     }
    15     int dp[c+1] = {0};
    16     for (int i = 1; i <= n; ++i) {
    17         //滚动数组这么写的时候,max(dp[j], dp[j-w[i-1]]+w[i-1]);如果是从左到右,那么dp[j-w[i-1]]是个已经被更新过的值。。
    18         //for (int j = 1; j <= c; ++j) {
    19         for (int j = c; j >= 1 ; --j) {
    20             if (j < w[i-1]) { dp[j] = dp[j]; }
    21             else {
    22                 dp[j] = max(dp[j], dp[j-w[i-1]]+w[i-1]);
    23             }
    24         }
    25     }
    26     cout << c - dp[c] << endl;
    27     return 0;
    28 }
    View Code

    P1616 疯狂的采药

    采药问题的升级版,不限制每种物品的个数。完全背包问题(每个物品无穷个)。

    完全背包的解法就是01背包的downto的写法改成正着写...不过这不是重点。重点是理解为啥需要正着写。

    提交一次AC了

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int main() {
     6     int T, M;
     7     cin >> T >> M;
     8     int w[M][2];
     9     for (int i = 0; i < M; ++i) {
    10         cin >> w[i][0] >> w[i][1];
    11     }
    12     int dp[T+1] = {0};
    13     for (int i = 1; i <= M; ++i) {
    14         for (int j = 1; j <= T; ++j) {
    15             if (j < w[i-1][0]) { continue; }
    16             else {
    17                 dp[j] = max(dp[j], dp[j-w[i-1][0]]+w[i-1][1]);
    18             }
    19         }
    20     }
    21     cout << dp[T] << endl;
    22     return 0;
    23 }
    View Code
  • 相关阅读:
    Jenkins的maven工程打包的时候怎么指定不同环境的配置文件
    杂记待整理
    zabbix监控网络的出入口流量
    MySQL的恢复脚本
    mysql 备份恢复图
    切割haproxy的日志
    zabbix 监控MySQL
    svn 的备份还原
    svn做目录访问控制(AuthzSVNAccessFile)
    MySQL多实例
  • 原文地址:https://www.cnblogs.com/zhangwanying/p/7647066.html
Copyright © 2011-2022 走看看