【C++背包】超级背包大集合

啊哈,经典的背包问题讲完了,这次呢,我们来总结一下背包问题,并整理程序。

总结

背包问题思路,就是将每一种放进去的情况都列举出来,并比较得到最优值,所以,就能求出最大值。这就是为什么背包问题中动态规划比普通递归要快,就是因为普通递归重复求了很多数值,而动态规划正好相反,把所有值存起来,对比值,求出,一般递归的时间复杂度是指数级,而动态规划基本上是平方级。

整理程序

(1) 01普通背包问题

#include<iostream>
#include<cstdio>
using namespace std;
int thing[1000001][3];         //重量(w)是thing[?][0],价值(c)是thing[?][1],f是thing[?][3] 
int max(int a,int b)
{
  return a>b? a:b;
}
int main()
{
  int n,V;
  cin>>V>>n;
    for(int i=1;i<=n;i++) cin>>thing[i][0]>>thing[i][1];
  for(int i=1;i<=n;i++)
  for(int v=V;v>=thing[i][0];v--)
  {
    thing[v][2]=max(thing[v][2],thing[v-thing[i][0]][2]+thing[i][1]);
   }
    cout<<thing[V][2];
     return 0;
}

(2)完全背包问题

#include<iostream>
#include<cstdio>
using namespace std;
int thing[1000001][3];         //如有数据内容不懂,请看上篇文章
int max(int a,int b)
{
 return a>b? a:b;
}
int main()
{
 int n,V;
 cin>>V>>n;
 for(int i=1;i<=n;i++) cin>>thing[i][0]>>thing[i][1];
  for(int i=1;i<=n;i++)
  for(int v=thing[i][0];v<=V;v++)
  {
   thing[v][2]=max(thing[v][2],thing[v-thing[i][0]][2]+thing[i][1]);
  }
 cout<<thing[V][2];
 return 0;
}

(3)多重背包问题

#include<cstdio>
int v[10001],w[10001];
int f[6001];
int n,m,n1;
int max(int a,int b)
{
 return a>b?a:b;
}
int main()
{
 scanf("%d%d",&n,&m);
 for(int i=1;i<=n;i++)
  {
  int x,y,s,t=1;
  scanf("%d%d%d",&x,&y,&s);
  while (s>=t)
  {
   v[++n1]=x*t;
   w[n1]=y*t;
   s-=t;
   t*=2;
  }
  v[++n1]=x*s;
  w[n1]=y*s;                             //把s以2的指数分堆:1,2,4,...,2^(k-1),s-2^k+1;
 }
 for(int i=1;i<=n1;i++)
  for(int j=m;j>=v[i];j--)
   f[j]=max(f[j],f[j-v[i]]+w[i]); 
 printf("%d",f[m]);
    return 0;

(4)混合背包

#include<iostream>
using namespace std;
int f[1000001],n[1000001],w[1000001],c[1000001];

int main()
{
    int N,V;
    cin>>V>>N;
    for(int i=1;i<=N;i++)
        cin>>w[i]>>c[i]>>n[i];
    for(int i=1;i<=N;i++)
    {
        if(n[i]!=0)
            for(int j=1;j<=n[i];j++) //最多多少个
                for(int v=V;v>=w[i];v--)
                    f[v]=max(f[v],f[v-w[i]]+c[i]);
        else
            for(int v=w[i];v<=V;v++)
                f[v]=max(f[v],f[v-w[i]]+c[i]);
    }
    int max=-99999999;
    for(int i=1;i<=V;i++) max=max<f[i]? f[i]:max;
    cout<<max;
    return 0;
 }

(5)二维费用的背包问题

#include<cstdio>
#include<cstring>
using namespace std;
int v, u, k;
int a[1001], b[1001], c[1001];
int f[101][101];
int main()
{
    memset(f,127,sizeof(f));
    f[0][0] = 0;
    scanf("%d%d%d",&v,&u,&k);
    for (int i = 1; i <= k; i++)
        scanf("%d%d%d",&a[i],&b[i],&c[i]);
    for (int i = 1; i <= k; i++)
      for (int j = v; j >= 0; j--)
        for (int l = u; l >= 0; l--)
        {
           int t1 = j+ a[i],t2 = l + b[i];
           if (t1 > v)  t1 = v;                        //若氮、氧含量超过需求,可直接用需求量代换,
           if (t2> u)  t2 = u;
           if (f[t1][t2] > f[j][l] + c[i])  f[t1][t2] = f[j][l] + c[i];
        }
    printf("%d",f[v][u]);
    return 0;
}

(6)分组背包

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int f[5000],c[5000],w[5000],a[5000][5000],i,j,n,m,s,k,t,p;
int main ()
{
 cin>>n>>m>>t;
 for (i=1; i<=m; i++)
   {
   cin>>w[i];
   cin>>c[i];
   cin>>p;
   a[p][0]++;
   a[p][a[p][0]]=i;
   }
 for (k=1; k<=t; k++)  
   for (i=n; i>=0; i--)
     for (j=1; j<=a[k][0]; j++)
       if (i>=w[a[k][j]])
         f[i]=max(f[i],f[i-w[a[k][j]]]+c[a[k][j]]);
 cout<<f[n];
 return 0; 
}

好了,背包问题到此结束,也希望大家多多学习掌握!

原文链接: https://www.cnblogs.com/Lotuses-robot/p/15385350.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    【C++背包】超级背包大集合

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/339454

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午12:05
下一篇 2023年3月2日 上午12:06

相关推荐