动态规划01背包-一维数组

动态规划01背包-一维数组

洛谷 P1049

 https://www.luogu.com.cn/problem/P1049

#include<bits/stdc++.h>
using namespace std;
//dp数组每个元素可看作为当前下标体积的箱子
int dp[20001],w[31];//dp[i]当前体积最大存放物品数量 w每个物品重量 
int main(){
    int v,n;//v箱子体积 总n个物品 
    cin>>v>>n;
    for(int i=1;i<=n;i++)//读取每个物品的体积 
        cin>>w[i];
        
    for(int i=1;i<=n;i++){//每个物品 模拟放到不同箱子 
    //v个箱子 从大到小放-dp[j-w[i]] 为不包含本物品的最大值,否则就包含了本物品最大值 
        for(int j=v;j>=0;j--){
            if(w[i]<=j){//体积比当前箱子体积小,才可以放入
                //dp[j] 不放入本次体积最大值 dp[j-w[i]]+w[i] 放入本次体积最大值 
                //dp[j-w[i]] 除本次对应小箱子最大价值 j-w[i]除本次的箱子的体积 
                dp[j]=max(dp[j],dp[j-w[i]]+w[i]);
            }
        }
    }
    cout<<v-dp[v];//总体积 - 本箱子放入物品最大体积 
    return 0;
}

 

 如果完全背包--每类物品可以放入多个的情况,则为如下所示:

 

洛谷 P1048

 https://www.luogu.com.cn/problem/P1048

#include <bits/stdc++.h>
using namespace std;
int t,m;//可采药时间 草药数目
int w[101], c[101];//w 每株采药花费时间  c每株采药价值 
int dp[1001];//i时间内采药最大价值 所有整数都计算 1-1001 
int main(){
    scanf("%d %d", &t, &m);
    for(int i=1; i <=m; i++) {
        scanf("%d %d", &w[i], &c[i]);
    }
    for(int i=1;i<=m;i++){
        //从t递减累加最大 可以保证dp[j-w[i]未计算本次 
        for(int j=t;j>=0;j--) {
            if(w[i]<=j){
            // dp[j] 不采最大价值,dp[j-w[i]] + c[i] 采药最大价值  
            // dp[j-w[i]] 除了本次以外最大价值,j-w[i] 扣除本次时间,c[i]本次价值 
                dp[j] = max(dp[j], dp[j-w[i]] + c[i]);
            }
        }
    }
    printf("%d", dp[t]);
    return 0;
}

 

洛谷P1060

https://www.luogu.com.cn/problem/P1060

#include<bits/stdc++.h>
using namespace std;
//v数组为money,w数组为重要度,dp数组 
int v[30],w[30],dp[50000];
int n,m;//n是总钱数 m是总物品个数,
int main(){
    cin>>n>>m;//输入
    for(int i=1;i<=m;i++){
        cin>>v[i]>>w[i];
        w[i]*=v[i];//w数组在这里意义变为总收获(重要度*money)
    }
    for(int i=1;i<=m;i++){
        for(int j=n;j>=0;j--){//注意从n开始
            if(j>=v[i]){
                dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
            }
        }
    }
    cout<<dp[n]<<endl;//背包大小为n时最大值
    return 0;
} 

 

洛谷P1164

https://www.luogu.com.cn/problem/P1164

https://blog.csdn.net/xiji333/article/details/87603160

#include<bits/stdc++.h>

using namespace std;
int n,m,price[110],dp[10010];
int main(){
   scanf("%d%d",&n,&m);//n种菜 m元钱 
   for(int i=1;i<=n;i++)
     scanf("%d",&price[i]);
   dp[0]=1;
   //加入每种才计算总点菜方法 
   for(int i=1;i<=n;i++){
           //每所有钱(n n-1 ...price[i])最大点菜方法 
           for(int j=m;j>=price[i];j--){
               dp[j]=dp[j]+dp[j-price[i]];
        }
   }
   //m元钱的最大点菜方法 
   cout<<dp[m];
   return 0;
}

洛谷P2871

https://www.luogu.com.cn/problem/P2871

#include<bits/stdc++.h>
using namespace std;
int n,m,dp[15000],c,w;
int main(){
    scanf("%d%d",&n,&m);//物品数量n 背包大小m 
    for(int i=1;i<=n;i++){
        scanf("%d%d",&c,&w);//读一个物品重量c和价值w 
        for(int j=m;j>0;j--){//背包剩余容量
            //如果可以放下,选放和不放价值大的 
            if(c<=j) dp[j]=max(dp[j],dp[j-c]+w);//取最大价值
        } 
             
    }
    printf("%d",dp[m]);//最后一个为最大值 
    return 0;    
}

 

posted @ 2021-04-18 09:40  new-code  阅读(426)  评论(0)    收藏  举报