⬅ 返回
1、法一 闫氏DP分析法

2、例题
3、代码
#include <iostream>
using namespace std;
const int N = 110;
int dp[N][N];
int v[N],w[N],s[N];
int n,m;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>v[i]>>w[i]>>s[i];
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
dp[i][j]=dp[i-1][j];//选择i物品0件的状态转移
for(int k=1;k<=s[i];k++)//从选择i物品1次开始遍历
{
if(k*v[i]<=j){
dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]*k]+w[i]*k);//更新
}else{
break;
}
}
}
}
cout<<dp[n][m]<<endl;
}
4、法二 将所有物品存储起来 看作01背包
4.1、二维 最大令N = 1e4 不推荐 空间不够
#include <iostream>
using namespace std;
const int N = 1e4;//最大
int n,m;
int dp[N][N];
int v[N],w[N],node=0;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int a,b,c;
cin>>a>>b>>c;
while(c--)
{
++node;
v[node]=a;
w[node]=b;
}
}
for(int i=1;i<=node;i++)
{
for(int j=0;j<=m;j++)
{
dp[i][j]=dp[i-1][j];
if(v[i]<=j)
{
dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]);
}
}
}
cout<<dp[node][m]<<endl;
}
4.2、一维优化
#include <iostream>
using namespace std;
const int N = 1e6+10;
int v[N],w[N],dp[N],node=0;
int n,m;
int main(){
cin>>n>>m;
while(n--)
{
int a,b,c;
cin>>a>>b>>c;
while(c--)
{
node++;
v[node]=a;
w[node]=b;
}
}
for(int i=1;i<=node;i++)
{
for(int j=m;j>=v[i];j--)
dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
}
cout<<dp[m]<<endl;
}
4.3、当物品的数量很多时、可以进行二进制优化
思路
代码
#include <iostream>
using namespace std;
const int N = 1e5+10;
int v[N],w[N],dp[N];
int node=0;
int n,m;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int a,b,c;
cin>>a>>b>>c;
int t=1;//t按照1 2 4 8 16 32 ........................
while(t<c){
node++;
v[node]=a * t;//把t个i物品捆包起来
w[node]=b * t;
c=c-t;
t=t*2;
}
if(c>0)//若不能刚好组合成2进制数,把剩余的捆包成一个物品
{
node++;
v[node]=a * c;
w[node]=b * c;
}
}
//01背包
------------------------------------------------
for(int i=1;i<=node;i++)
{
for(int j=m;j>=v[i];j--)
{
dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
}
}
-------------------------------------------------------------------
cout<<dp[m]<<endl;
}