携带研究材料

题目

限制条件是背包的空间,目标是实现价值最大。输出是最大价值。研究材料的种类是含有映射关系数组的长度。

初始思路

1.找到比行李箱空间小的所有的材料;这是一个含有映射关系的数组
2.对该数组做空间小于给定空间的所有组合,并记录价值总和;这是个组合问题
3.找出价值最大的组合。
组合问题包含回溯过程,且按下不表。

DP的思路

1.DP[i][j]表示在容量为j的背包里放(0,i)物品的最大价值。
2.递推:因为dp[i][j]表示的是问题的解,即达到的最大价值。这是一个动态的过程,包含的不确定是每一件物品都有可能放进去或者没放进去。无论如何,上一个状态一定是dp[i-1][j],如果没放物品: dp[i][j]=dp[i-1][j];如果放入物品:dp[i][j]=dp[i-1][j-weight[i]]+value[i];
3.数组初始化:dp[i][j]代表问题的解,往里面放东西是容量固定,即一件一件放,是列。
dp[0][0]=0;dp[0,1]=?取决于第0件物品的weight有没有超过背包的容量,如果没超过,那么dp[0,1]=value[0],如果放不下,dp[0,1]=0;
dp[1,0]=0;dp[i,0]=0;
4.遍历序:
5.DP数组举例:
5,4
2 1 6 4 8
2 2 3 2 2
输出:
0 0 2 2 2
0 2 2 4 4
0 2 2 4 4
0 2 2 4 4

其中,weight.size就是n;

DP和贪心

贪心放远一点看当前的状态与过往的状态联系并不十分密切;买柠檬水收钱,后面的状态你总是有钱找的,前面的状态不一定会影响当前的状态。
DP则是一种累加效应,放进去就一定占地方。每一个状态都会影响后来的状态。

背包一维解法

#include<iostream>
#include<bits/stdc++.h>
#include<vector>
using namespace std;

int main(){
    int n,bagweight;
    cin>>n>>bagweight;
    vector<int> weight(n,0);
    vector<int> value(n,0);

    for(int i=0;i<n;i++){
        cin>>weight[i];
    }
    for(int j=0;j<n;j++){
        cin>>value[j];
    }
    vector<int> dp(bagweight+1,0);
    //初始化
    for(int j=weight[0];j<=bagweight;j++){
        dp[j]=value[0];
    }
    //递推条件
    for(int i=1;i<n;i++){
        for(int j=bagweight;j>=weight[i];j--){
                dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
            cout<<dp[j]<<endl;
        }
        
    }
    cout<<dp[bagweight]<<endl;
    return 0;
}

分割等和子集

似曾相识,求一个数组中和为固定值的组合。

posted on 2025-12-15 18:00  FAfa_C++  阅读(4)  评论(0)    收藏  举报