动态规划解决背包问题

目录

目录

动态规划步骤:

1.01背包问题

(一)二维数组dp[i] [j]

(二)一维滚动数组dp[j] 

2.完全背包问题

(一)二维数组dp[i][j]

(二)一维数组dp[j]


动态规划步骤:

 step1.分析问题,定义dp数组(下标含义)

step2.初始化dp数组(边界)

step3.写dp状态转换方程(明确dp数组遍历顺序)

1.01背包问题

        即物品均只能取1次

46. 携带研究材料(第六期模拟笔试) (kamacoder.com)icon-default.png?t=N7T8https://kamacoder.com/problempage.php?pid=1046

(一)二维数组dp[i] [j]

#include <iostream>
#include <vector>
using namespace std;

void debug_input(vector<int>& vec){
    for(auto it=vec.begin(); it!=vec.end(); it++){
        cout<<*it<<" ";
    }
    cout<<endl;
}

class solution
{
public:
    int max_value(vector<int>& space, vector<int>& value, int M, int N){
        // 定义dp[i][j]
        vector<vector<int>> dp(M+1, vector<int> (N+1, 0));
        //初始化
        for(int j=space[0]; j<=N; j++)
            dp[0][j] = value[0];
        //状态转换
        for(int i=1; i<M; i++){
            for(int j=1; j<=N; j++){
                if(j < space[i]) dp[i][j] = dp[i-1][j];
                else dp[i][j] = max( dp[i-1][j], dp[i-1][j-space[i]] + value[i]); 
            }
        }
        return dp[M-1][N];
    }
};

int main(){
    // input
    int M,N,input;
    cin>>M>>N;
    vector<int> space(M,0);
    vector<int> value(M,0);
    for(int i=0; i<M; i++){
        cin>>input;
        space[i] = input;
    }
    for(int i=0; i<M; i++){
        cin>>input;
        value[i] = input;
    }
    // // debug input
    // debug_input(space);
    // debug_input(value);
    
    //solve
    solution mysolve;
    cout<<mysolve.max_value(space, value, M, N);
    
    return 0;
}

(二)一维滚动数组dp[j] 

#include <iostream>
#include <vector>
using namespace std;

class solution
{
 public:
    int max_value(vector<int>& space, vector<int>& value, int M, int N){
        //定义滚动dp[j]
        vector<int> dp(N+1,0);
        //状态转换
        for(int i=0;i<M;i++){       // 先遍历物品
            for(int j=N;j>=space[i];j--){   // 再逆序遍历背包容量
                dp[j] = max( dp[j], dp[j-space[i]]+value[i] ); 
            }
        }
        return dp[N];
    }
};

int main(){
   //input
   int M,N,input;
   cin>>M>>N;
   vector<int> space(M,0);
   vector<int> value(M,0);
   while(1){
       for(int i=0; i<M; i++){
           cin>>input;
           space[i] = input;
       }
       for(int i=0; i<M; i++){
           cin>>input;
           value[i] = input;
       }
       break;
   }
   //solve
   solution res;
   cout<<res.max_value(space, value, M, N);
   
   return 0; 
}

 

2.完全背包问题

        即满足条件下,每个物品可取无数次。 

52. 携带研究材料(第七期模拟笔试) (kamacoder.com)icon-default.png?t=N7T8https://kamacoder.com/problempage.php?pid=1052 

   (一)二维数组dp[i][j]

#include <iostream>
#include <vector>
using namespace std;

void debug_input(vector<int>& vec){
    for(auto it=vec.begin(); it!=vec.end(); it++){
        cout<<*it<<" ";
    }
    cout<<endl;
}

class solution
{
public:
    int max_value(vector<int>& space, vector<int>& value, int total_num, int total_space){
        // 定义dp[i][j]
        vector<vector<int>> dp(total_num, vector<int> (total_space+1, 0));
        //初始化
        for(int j=space[0]; j<=total_space; j++){
            dp[0][j] = dp[0][j-space[0]] + value[0];
        }
        //状态转换
        for(int i=1; i<total_num; i++){
            for(int j=1; j<=total_space; j++){
                if(j < space[i]) dp[i][j] = dp[i-1][j];
                else dp[i][j] = max( dp[i-1][j], dp[i][j-space[i]]+value[i]);
            }
        }
        return dp[total_num-1][total_space];
    }
};

int main(){
    //input
    int total_num, total_space;
    cin>>total_num>>total_space;
    vector<int> space(total_num,0);
    vector<int> value(total_num,0);
    int s, v;
    for(int i=0; i<total_num; i++){
        cin>>s>>v;
        space[i] = s;
        value[i] = v;
    }
    // debug_input(space);
    // debug_input(value);
    
    //solve
    solution mysolve;
    cout<<mysolve.max_value(space, value, total_num, total_space);
    return 0;
}

(二)一维数组dp[j]

#include <iostream>
#include <vector>
using namespace std;

class solution
{
 public:
    int max_value(vector<int>& space, vector<int>& value, int N, int V){
        //定义滚动dp[j]
        vector<int> dp(V+1,0);
        //状态转换
        for(int i=0;i<N;i++){       
            for(int j=space[i];j<=V;j++){   
                dp[j] = max( dp[j], dp[j-space[i]]+value[i] ); 
            }
        }
        return dp[V];
    }
};

int main(){
   //input
   int N,V,w,v;
   cin>>N>>V;
   vector<int> space(N,0);
   vector<int> value(N,0);
   while(1){
       for(int i=0; i<N; i++){
           cin>>w>>v;
           space[i] = w;
           value[i] = v;
       }
       break;
   }
   //solve
   solution res;
   cout<<res.max_value(space, value, N, V);
   
   return 0; 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值