zoukankan      html  css  js  c++  java
  • dp小结|背包问题

    1.先放上0-1背包模板

    二维数组

    for(int i=1;i<=n;i++)//枚举 物品 
        for(int j=1;j<=V;j++)//枚举体积 
        //这个位置是可以正序枚举的.  qwq
        //一维01背包必须倒叙  emmm
        //这个没错a emmm  
            if(j>=c[i])
                f[i][j]=max(f[i-1][j],f[i-1][j-c[i]]+w[i]);//状态转移方程.
            else f[i][j]=f[i-1][j].
    
    

    滚动二维数组

        int dp[2][10010];
        int row = 0; //滚动 
        for (int i = 1; i < n; ++i) {
            row = 1 - row;
            for (int j = 1; j <= i * (i + 1) / 2; ++j) {//这里可以减少枚举
            if(j>=c[i])
                f[row][j]=max(f[1-row][j],f[1-row][j-c[i]]+w[i]);//状态转移方程.
            else f[row][j]=f[1-row][j].
            }
        }
    

    一维数组(逆序)

    for(int i=1;i<=n;i++)//枚举 物品 
        for(int j=V;j>=c[i];j--)//枚举体积 
            f[j]=max(f[j],f[j-c[i]]+w[i]);//状态转移方程. 
    

    模板题:洛谷:P1048采药
    “采药”这道题套模板就行了,从二维到一维优化。

    2.顺便再复习记忆化搜索洛谷:P1048采药记忆化搜索做法题解

    先想到dfs搜索暴力解题,就是多参数递归,出口记录搜索到的值
    再想到记忆化搜索,什么时记忆化搜索?记录每一次dfs答案,免去重复计算,从而起到优化时间复杂度的作用
    记忆化搜索记录什么值呢?记录每次搜索结束找到的价值(不一定最大)

    如何想到可以用记忆化搜索?

    3.蓝桥杯考过的记忆化搜索——2013年C++B组第9题地宫取宝

    使用四维数组缓存记录。

    4.蓝桥杯考过的0-1背包:2014年C++A组第十题-波动数列

    这道题比较难想到0-1背包,选数字对应成拿物品填充背包,dp[i][j]表示用前i个数凑出数字j的方案数,类似题目:我记得有一道选几个数字,凑出数字n。初始化dp[0][0] = 1,第0列都等于1,dp[i~n][0] = 1

    5.完全背包

    与0-1背包略有不同的是,每种物品有无限多个,可重复选取。

    二维数组,三层循环模板

    for(int i=1;i<=n;i++)//枚举物品
        for(int j=1;j<=V;j++)
            for(int k=1;k<=V/c[i];k++)//我们的物品最多只能放多少件.  
                {
                    if(k*c[i]<=j)
                        f[i][j]=max(f[i-1][j],f[i-1][j-k*c[i]]+k*w[i]);
                    else 
                        f[i][j]=f[i-1][j];
                     //判断条件与01背包相同.
                }
    

    一维数组,两层循环模板(顺序枚举,和0-1背包一维恰好相反)

    for(int i=1;i<=n;i++)//枚举物品
        for(int j=c[i];j<=V;j++)//枚举体积.注意这里是顺序/
            f[j]=max(f[j],f[j-c[i]]+w[i]);//状态转移.
    

    完全背包模板题:P1616 疯狂的采药

    6.蓝桥杯考过的完全背包:2017年蓝桥杯-包子凑数

    1~100000(比较大的值)
    初始化dp[0] = 1
    完全背包思想,推出布尔类型的dp数组,最后遍历最后dp数组最后一层为true的个数

    整数划分(每个数可以用无限次)——完全背包

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 100005;
    int n;
    int dp[maxn];
    
    int main(){
    	cin>>n;
    	dp[0] = 1;
    	for(int i=1;i<=n;i++){//可以用到n 
    		for(int j=i;j<=n;j++){//完全背包 每个数字可以用无限次 
    			dp[j] = dp[j] + dp[j-i];
    		}
    	}
    	cout<<dp[n]<<endl;
    	return 0;
    } 
    

    整数划分(每个数只能用一次)——0-1背包

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 100005;
    int n;
    int dp[maxn];
    
    int main(){
    	cin>>n;
    	dp[0] = 1;
    	for(int i=1;i<=n-1;i++){//不能用n 
    		for(int j=n;j>=i;j--){//0-1背包 倒序 
    			dp[j] = dp[j] + dp[j-i];
    		}
    	}
    	cout<<dp[n]<<endl;
    	return 0;
    } 
    //输入6
    //输出3  说明:1、5;2、4;1、2、3 
    

    7.多重背包,没做过题不好讲复习。。

    多重背包问题限定了一种物品的个数,一个简单的方法,转成0-1背包。先这样写吧

    #include <iostream>
    using namespace std;
    #define V 1000
    int weight[50 + 1];
    int value[50 + 1];
    int num[20 + 1];
    int f[V + 1];
    int max(int a, int b) {
        return a > b ? a : b;
    }
    int main() {
        int n, m;
        cout << "请输入物品个数:";
        cin >> n;
        cout << "请分别输入" << n << "个物品的重量、价值和数量:" << endl; 
        for (int i = 1; i <= n; i++) {
            cin >> weight[i] >> value[i] >> num[i];
        }
        int k = n + 1;
        for (int i = 1; i <= n; i++) {
            while (num[i] != 1) {
                weight[k] = weight[i];
                value[k] = value[i];
                k++;
                num[i]--;
            }
        }
        cout << "请输入背包容量:";
        cin >> m;
        for (int i = 1; i <= k; i++) {
            for (int j = m; j >= 1; j--) {
                if (weight[i] <= j) f[j] = max(f[j], f[j - weight[i]] + value[i]);
            }
        }
        cout << "背包能放的最大价值为:" << f[m] << endl;
    }
    

    学长的dp:https://blog.csdn.net/o_ohello/article/details/89378697

  • 相关阅读:
    SPOJ913 Query on a tree II
    SPOJ375 Query on a tree
    HDU4348 To the moon
    Bzoj2753 [SCOI2012]滑雪与时间胶囊
    HDU4612 Warm up
    Uva11374 Airport Express
    Uva1624 Knots
    DevExpress的GridControl的使用以及怎样添加列和绑定数据源
    C#中使用Path、Directory、Split、Substring实现对文件路径和文件名的常用操作实例
    ZedGraph的曲线的LineItem对象的Tag属性存储信息进而在鼠标悬浮时进行显示
  • 原文地址:https://www.cnblogs.com/fisherss/p/10561139.html
Copyright © 2011-2022 走看看