1.01背包问题:
方法一:贪心算法(按价值排序,依次选取)但是局部最优并不能保证全局最优
方法二:贪心算法(按性价比排序,依次选取)但是局部最优并不能保证全局最优
方法三:枚举法(用子集树枚举出所有的方案,然后挑选符合要求的最佳方案)缺点是时间复杂度太高(指数级复杂度)
方法四:动态规划
#include<bits/stdc++.h>
using namespace std;
int n, m;//n表示物品数量,m表示背包容量
int w[1000], v[1000];//w表示物品重量,v表示物品价值
int f[1000][1000];//前i个物品装进容量为j背包中的最大值
int main()
{
cin>>m>>n;
for(int i=1;i<=n;i++)
{
cin>>w[i]>>v[i];
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)//m为背包容量
{
if(j<w[i])
{
f[i][j]=f[i-1][j];
}
else
{
f[i][j]=max(f[i-1][j], f[i-1][j-w[i]]+v[i]);//j-w[i]为箭头的起点
}
}
}
cout<<f[n][m];
return 0;
}
/*
10 4
2 1
3 3
4 5
7 9
*/
用一维数组实现:
关键点
1.从右向左填
2.使用滑动窗口的方法,右端点的值=左端点的值+第i个物品的价值
#include<bits/stdc++.h>
using namespace std;
int n, m;//n表示物品数量,m表示背包容量
int w[1000], v[1000];//w表示物品重量,v表示物品价值
int f[1000];//前i个物品装进容量为j背包中的最大值
int main()
{
cin>>m>>n;
for(int i=1;i<=n;i++)
{
cin>>w[i]>>v[i];
}
for(int i=1;i<=n;i++)
{
for(int j=m;j>=w[i];j--)//m为背包容量
{
f[j]=max(f[j], f[j-w[i]]+v[i]);
}
}
cout<<f[m];
return 0;
}
/*
10 4
2 1
3 3
4 5
7 9
*/
2.完全背包问题:
关键点:
1.从左向右填(与01背包问题相反)
2.使用滑动窗口的方法,右端点的值=左端点的值+第i个物品的价值(与01背包问题相同)
#include<bits/stdc++.h>
using namespace std;
int n, m;//n表示物品数量,m表示背包容量
int w[1000], v[1000];//w表示物品重量,v表示物品价值
int f[1000];//前i个物品装进容量为j背包中的最大值
int main()
{
cin>>m>>n;
for(int i=1;i<=n;i++)
{
cin>>w[i]>>v[i];
}
for(int i=1;i<=n;i++)
{
for(int j=w[i];j<=m;j++)//m为背包容量
{
f[j]=max(f[j], f[j-w[i]]+v[i]);
}
}
cout<<"max="<<f[m];
return 0;
}
/*
10 4
2 1
3 3
4 5
7 9
*/