• 背包


    动态规划:

    ## 动态规划原理

    • 基本思想:问题的最优解如果可以由子问题的最优解推导得到,则可以先求解子问题的最优解,在构造原问题的最优解;若子问题有较多的重复出现,则可以自底向上从最终子问题向原问题逐步求解。
    • 使用条件:可分为多个相关子问题,子问题的解被重复使用
      • Optimal substructure(优化子结构):
        • 一个问题的优化解包含了子问题的优化解
        • 缩小子问题集合,只需那些优化问题中包含的子问题,降低实现复杂性
        • 我们可以自下而上的
      • Subteties(重叠子问题):在问题的求解过程中,很多子问题的解将被多次使用。
    • 动态规划算法的设计步骤:
      • 分析优化解的结构
      • 递归地定义最优解的代价
      • 自底向上地计算优化解的代价保存之,并获取构造最优解的信息
      • 根据构造最优解的信息构造优化解
    • 动态规划特点:
      • 把原始问题划分成一系列子问题;
      • 求解每个子问题仅一次,并将其结果保存在一个表中,以后用到时直接存取,不重复计算,节省计算时间
      • 自底向上地计算。
      • 整体问题最优解取决于子问题的最优解(状态转移方程)(将子问题称为状态,最终状态的求解归结为其他状态的求解)
    01背包:有n种物品与承重为m的背包。每种物品只有一件,每个物品都有对应的重量weight[i]与价值value[i],求解如何装包使得价值最大。
    dp(i,v)表示前i个物体(包括第i个)面对容量为v的背包的最大价值,c[i]代表物体i的重量,w[i]代表物体i的价值;如果第i个物体不放入背包,则背包的最大价值等于前i-1个物体面对容量v的最大价值;如果第i个物体选择放入,则背包的最大价值等于前i-1个物体面对容量v-cost[i]的最大价值加上物体i的价值w[i]。
    对于实现,一般采用一个二维数组(状态转移矩阵)dp[i][j]来记录各个子问题的最优状态,其中dp[i][j]表示前i个物体面对容量j背包的最大价值。
    下面给出0-1背包的基本实现,时间复杂度为O(N*V),空间复杂度也为O(N*V)
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    const int maxn = 1e3+5;
    int dp[maxn][maxn];
    int weight[maxn];
    int value[maxn];
    int main(){
        int n,m;
        cin>>n>>m;
        memset(dp,0,sizeof(dp));
        for(int i = 1;i<=n;i++){
            scanf("%d%d",&w[i],&v[i]);
        }
        for(int i=1;i<=n;i++){
            for(int j=0;j<=m;j++){
                if(j<w[i]){
                    dp[i][j] = dp[i-1][j];
                }
                else
                    dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]); 
            }
        }
        cout<<dp[n][m]<<endl;
        return 0;
    }

     /*
    1489.特大背包问题 (20分)
    C时间限制:1000 毫秒 |  C内存限制:10000 Kb
    题目内容:
    现在有一个容量为C的背包和N个重量和价值已知的物品. 现在要从这n个物品中挑选出一些物品, 使得选择的物品的总重量不超过背包的容量, 且总价值最大.
    此题的数据范围:
    1 <= C <= 10^8(10的8次方)
    1 <= N <= 100
    输入描述
    有多组测试数据. 第一行一个正整数T(T<=15), 表示测试数据组数.
    对于每组测试数据:
    第一行两个正整数N和C, 分别表示物品的数量和背包的容量.
    接下来N行, 每行两个正整数w,v ,分别表示对应物品的重量和价值(1<= w <= 10^7, 1<= v <= 100)

    输出描述
    输出一个正整数, 表示在所选物品不超过背包容量的情况下, 能够得到的最大价值.

    输入样例
    1
    3 10
    5 10
    5 10
    4 12

    输出样例
    22*/

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e2;
    const int INF = 0x3f3f3f3f;
    ll dp[maxn+1][maxn*maxn+1];
    int n;
    ll c;
    ll w[maxn],v[maxn];
    int main(){
        int t;
        cin>>t;
        while(t--){
            scanf("%d%lld",&n,&c);
            int m = 0;
            for(int i=0;i<n;i++){
                scanf("%lld%lld",&w[i],&v[i]);
            }
            fill(dp[0],dp[0]+maxn*maxn+1,INF);
            dp[0][0]=0;
            for(int i=0;i<n;i++){
                for(int j = 0;j<=maxn*maxn;j++){
                    if(j<v[i]){
                        dp[i+1][j] = dp[i][j];
                    }
                    else
                        dp[i+1][j] =min(dp[i][j],dp[i][j-v[i]]+w[i]);
                }
            }
            int res = 0;
            for(int i=0;i<=maxn*maxn;i++){
                if(dp[n][i]<=c){
                    res = i;
                }
            }
            cout<<res<<endl;
            
            
        }
        return 0;
    }
  • 相关阅读:
    eclipse设置字体大小
    如何利用服务器下发的Cookie实现基于此Cookie的会话保持
    Docker学习笔记_安装和使用Python
    Docker学习笔记_安装和使用mysql
    Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.38/images/json: dial unix /var/run/docker.sock: conne
    Ubuntu18.04创建新的系统用户
    Docker学习笔记_安装和使用nginx
    Docker安装和使用Tomcat
    虚拟机ubuntu18.04设置静态IP
    我学习参考的网址
  • 原文地址:https://www.cnblogs.com/lusiqi/p/11628684.html
Copyright © 2020-2023  润新知