完全背包

题目描述

即0-1背包,把每个物品只能拿一次改为能拿无数次。

思路

//这个位置的状态是不拿,第一次拿,和第n>1次拿
dp[i][j]=max(max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]),dp[i][j-v[i]]);
拿0次:dp[i-1][j];
拿1次:dp[i-1][j-v[i]]+w[i];
拿2次:dp[i-1][j-v[i]*2]+w[i]*2;
拿3次:dp[i-1][j-v[i]*3]+w[i]*3;
拿n次:dp[i-1][j-v[i]*n]+w[i]*n;
在拿了一次之后:dp[i][j]更新为dp[i-1][j-v[i]]+w[i];
拿第二次时可以直接拿第一次拿的结论d[i][j-v[i]]直接转移。

一维数组优化

#include <bits/stdc++.h>
using namespace std;
int dp[1000];
int main(){
    int w[110],v[110];
    int t,m;
    cin>>t>>m;
    for(int i=1;i<=m;i++){
        cin>>w[i]>>v[i];
    }
    for(int i=1;i<=m;i++){
        for(int j=0;j<=t;j++){//0-1背包是从后往前,千万不要弄混
            if(j>=w[i]){
                dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
            }else{
                dp[j]=dp[j];
            }
        }
    }
/*    for(int i=0;i<=m;i++){
        for(int j=0;j<=t;j++){
            cout<<dp[i][j]<<" ";
        }
        cout<<endl;
    }
*/    cout<<dp[t];
    return 0;
} 

posted on 2019-06-16 19:57  nodeee  阅读(74)  评论(0编辑  收藏  举报