1)01背包
每个物品每次只能用一次。
二维数组版:
const int N = 1010;
int w[N], dp[N][N], v[N];
int n, m;
scanf("%d%d", &n, &m);
for(int i =1; i<= n; i++)
{
cin>>v[i]>>w[i];
}
for(int i=1; i<=n; i++)
{
for (int j=1; j<=m; j++)
{
dp[i][j] = dp[i-1][j];
if(v[i] <= j) dp[i][j] = max(dp[i][j], dp[i-1][j-v[i]] + w[i]);
}
}
cout<<dp[n][m];
一维优化版:
const int N = 1010;
int w[N], dp[N], v[N];
int n, m;
scanf("%d%d", &n, &m);
for(int i =1; i<= n; i++)
{
cin>>v[i]>>w[i];
}
for(int i=1; i<=n; i++)
{
for (int j=m; j>=v[i]; j--)
{
dp[j] = max(dp[j], dp[j-v[i]] + w[i]);
}
}
cout<<dp[m];
2)完全背包
每个物品能放无限多个;
优化版:
const int N = 1010;
int w[N], dp[N], v[N];
int n, m;
scanf("%d%d", &n, &m);
for(int i =1; i<= n; i++)
{
cin>>v[i]>>w[i];
}
for(int i = 1; i<=n; i++)
{
for (int j= v[i] ; j<= m; j++)
{
dp[j] = max(dp[j], dp[j-v[i]] +w[i]);
}
}
cout<<dp[m];
3)多重背包
每个物品能放有限个。
暴力01
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i<= n; i++)
{
scanf("%d%d%d", &v[i], &w[i], &s[i]);
}
for(int i = 1; i<= n; i++)
{
for(int j =0; j<= m; j++ )
{
for(int k = 0; k<= s[i]; k++)
{
if(k*v[i] <= j) dp[i][j] = max(dp[i][j], dp[i-1][j- k*v[i]] + k*w[i]);
}
}
}
cout<<dp[n][m];
暴力优化:
int n, m;
cin>>n>>m;
for(int i =1; i<=n; i++)
{
int v, w,s;
cin>>v>>w>>s;
for(int k=1; k<=s; k++)
{
for(int j = m; j>=v; j--)
{
dp[j] = max(dp[j], dp[j-v] + w);
}
}
}
cout<<dp[m];
二进制优化:把数量[0, s]数组利用二进制转换为logn的二进制数组[1, 2, 4……k] k<=s, k%2 == 0,该数组能凑成0~s间所有的数。
int n, m;
cin>>n>>m;
vector< pair<int, int> > q;
q.push_back(make_pair(0, 0 ));
for(int i =1; i<=n; i++)
{
int v, w, s;
cin>>v>>w>>s;
for(int k = 1; k<=s; k++)
{
s -= k;
q.push_back(make_pair(k*v, k*w));
}
if(s) q.push_back(make_pair(s*v, s*w));
}
for(int i =1; i<= (int) q.size(); i++)
for(int j=m; j>=q[i].first; j-- )
dp[j] = max(dp[j], dp[j-q[i].first]+q[i].second);
cout<< dp[m];
4)分组背包
每组物品只能选一个放入背包;
二维数组版:
int n, m;
cin>>n>>m;
for(int i = 1; i<= n; i++)
{
cin>>s[i];
for(int k = 1; k<= s[i]; k++)
cin>>v[i][k]>>w[i][k];
}
for(int i = 1; i <= n; i++ )
{
for(int j = m; j >= 0; j--)
{
dp[i][j] = dp[i-1][j];
for(int k = 0; k <= s[i]; k++)
{
if(v[i][k] <= j) dp[i][j] = max(dp[i][j], dp[i-1][j-v[i][k]] + w[i][k]);
}
}
}
cout<<dp[n][m];
一维优化版:
int n, m;
cin>>n>>m;
for(int i = 1; i<= n; i++)
{
cin>>s[i];
for(int k = 1; k<= s[i]; k++)
cin>>v[i][k]>>w[i][k];
}
for(int i = 1; i <= n; i++ )
{
for(int j = m; j >= 0; j--)
{
for(int k = 0; k <= s[i]; k++)
{
if(v[i][k] <= j) dp[j] = max(dp[j], dp[j-v[i][k]] + w[i][k]);
}
}
}
cout<<dp[m];