AcWing-01背包问题
题目描述
有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。
第 i 件物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0
4 5
1 2
2 4
3 4
4 5
输出样例:
8
状态转移方程如下
s(i,j) = max (s(i-1,j), s(i-1,j-v)+w )
#include
#include
using namespace std;
const int N=1010;
int v[N],w[N];
int s[N][N];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
s[i][j]=s[i-1][j]; // 初始化s[i][j]
if(j>=v[i])
s[i][j]=max(s[i][j],s[i-1][j-v[i]]+w[i]);
}
}
cout<<s[n][m];
return 0;
}
#include
#include
using namespace std;
const int N=1010;
int v[N],w[N];
int s[N];
int main()
{
int n,m;
cin>>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--) // 注意从右向左
{
s[j]=max(s[j],s[j-v[i]]+w[i]);
}
}
cout<<s[m];
return 0;
}
AcWing-完全背包问题
题目描述
有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用。
第 i 种物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 种物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0
4 5
1 2
2 4
3 4
4 5
输出样例:
10
状态转移方程
1、s(i,j) = max (s(i-1,j), s(i-1,j-v)+w, s(i-1,j-2v)+2w ...)
2、s(i,j-v) = max (s(i-1,j-v), s(i-1,j-2v)+w ...) // 注意没有 +w
1 和 2 合并后可得
s(i,j) = max (s(i-1,j), s(i,j-v)+w )
#include
#include
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int s[N][N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
s[i][j]=s[i-1][j]; // 初始化s[i][j]
if(j>=v[i])
s[i][j]=max(s[i][j],s[i][j-v[i]]+w[i]);
}
}
cout<<s[n][m];
return 0;
}
#include
#include
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int s[N];
int main()
{
cin>>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++) // 从左到右
{
s[j]=max(s[j],s[j-v[i]]+w[i]);
}
}
cout<<s[m];
return 0;
}
1、
状态转移方程的差异:
01背包:
s(i,j) = max (s(i-1,j), s(i-1,j-v)+w )
完全背包:
s(i,j) = max (s(i-1,j), s(i,j-v)+w )
只差了个“-1”
2、
根据上面两个题可以看到,在一维解法中,两者都存在这一条语句:
s[j]=max(s[j],s[j-v[i]]+w[i]);
不同的是,01背包是从右向左:
for(int i=1;i<=n;i++)
{
for(int j=m;j>=v[i];j--) // 注意从右向左
{
s[j]=max(s[j],s[j-v[i]]+w[i]);
}
}
而完全背包是从左向右:
for(int i=1;i<=n;i++)
{
for(int j=v[i];j<=m;j++) // 从左到右
{
s[j]=max(s[j],s[j-v[i]]+w[i]);
}
}