动态规划-01背包
1:01背包问题只有两种两种状态:放进背包或者不放进背包。
2:01背包的核心:状态转换方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-Wi](i从1到N循环,j从0到V循环)//表示前i件物品,放入容量为j的背包所能获得的最大收益
//其中dp[i-1][j]表示第i件没有放入背包时候的收益,dp[i-1][j-Wi]+Vi表示第i件物品放入背包时候的收益
对状态转换方程进行优化:dp[j]=max(dp[j],dp[j-Wi]+Vi) (i从1循环到N,j从V循环到0) //j从大到小循环是为了保证,当一个物品可以循环多次的时候
3:01背包经典例题: dp[j-Wi]的值不会被新的数据覆盖
代码:
#include<algorithm>
#include<iostream>
using namespace std;
int main ()
{
int N,V,W[1005],V[1005],dp[1005];
cin>>N>>V;
for(int i=1;i<=N;i++) //输入
cin>>W[i]>>V[i];
for(int i=1;i<=N;i++) //01背包
for(int j=V;j>=0;j--)
{
if(j<W[i]) break;
dp[j]=max(dp[j],dp[j-W[i]]+V[i]);
}
cout<<dp[V]<<endl; //输出
return 0;
}
4:01背包的变式应用:https://www.luogu.com.cn/problem/P2392
代码:
#include<algorithm> //在c++中使用max函数需要使用的头文件
#include<iostream>
using namespace std;
int a[5],dp[1205],sum,homework[100],tot;
int main()
{
for (int i = 1;i <= 4;i++) cin >> a[i];
for (int i = 1;i <= 4;i++)
{
sum = 0;
for (int j = 1;j <= a[i];j++)
{
cin >> homework[j];
sum += homework[j]; //累计完成这一科习题需要的时间总和
for(int j=1;j<=a[i];j++) //假设左脑所用的时间小于等于总时间的一半,则右脑所用的时间一定会大于或者等于总时间的一半
for (int k = sum / 2;k >= homework[j];k--) //dp[k]表示时间容量为k时,左脑能够完成的时间
dp[k] = max(dp[k], dp[k - homework[j]] + homework[j]);
tot += sum - dp[sum/2]; //总的时间-左脑消耗的时间=右脑消耗的时间(即完成这一组习题所需要的时间)
for (int k = 1;k <= sum / 2;k++) dp[k] = 0; //清零
}
cout << tot << endl;
return 0;
}