aXiangYa

导航

动态规划-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;
}

posted on 2020-09-14 10:20  aXiangYa  阅读(113)  评论(0编辑  收藏  举报