10.10学习总结

来源:互联网 发布:seo诊断 编辑:程序博客网 时间:2024/04/30 23:13

嗯,依然是补上前两天的坑,假装现在是10.10.
今天复习了lch的讲课内容,关于动规的拓展与延伸,
今天对背包问题进行了一个大的总结
总的来说背包问题分为6类
1.01背包
非常经典的背包问题,直接见代码

for(int i=1;i<=n;i++)    {           for(int j=v;j>=c[i];j--)            f[j]=max(f[j],f[j-c[i]+w[i]);    }

2.完全背包
其实与01背包差不多,不过是对于同一件物品的数量不限制。

for(int i=1;i<=n;i++)    {           tot+=c[i];        bound=max(c[i],v-tot);        for(int j=bound;j<=v;j++)            f[j]=max(f[j],f[j-c[i]+w[i]);    }

与01背包相比,只是在第二个循环处有改动。
3.多重背包
此问题有两种思路,与完全背包近似,一种是都化成01背包,一种是二进制背包求解,还有一种算法用优先队列可以达到O(NV)的,但是并没有学习,以后回来再填坑,先发出对于背包二进制处理的代码

4.混合背包,此问题应分解处理,将背包分为3类
代码很容易理解
设置一个标志数组bag[],值为0是01背包,1是完全背包,2是多重背包

for (int i=1;i<=n;i++){    tot+=c[i];    bound=max(c[i],v-tot);    if (bag[i]=0)    for (int j=v;j>=bound;j--)        f[j]=max(f[j],f[j-c[i]]+w[i]);    else if (bag[i]=1)    for (int j=bound;j<=v;j++)        f[j]=max(f[j],f[j-c[i]]+w[i]);    else *二进制分解

5.分组背包
此问题是需要添加一重循环来记录组数,也是非常简单,见代码

for(int i=1;i<=n;i++)//此处i为组数    for (int j=v;j>0;j--)//分组背包应先循环v使得一次只添加进一个物品        for (int l=1;l<=k;l++)            if (c[i][l]>j)coutinue;            else f[j]=max(f[j],f[j-c[i][l]]+w[i][k]);

6.有依赖性背包问题
此类问题较难
如NOIP2006的金明的预算方案,此问题的思想是对于每一组数据先对其进行01背包,然后此问题将转换为一个(树形动规)问题。

#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<deque>using namespace std;int ans=0,t,a[61][10],c[61][10],next[61],tail,n,m,v,p,q;int dp[61][32010];int main(){        cin>>m>>n;    memset(a,0,sizeof(a));    memset(dp,0,sizeof(dp));    for (int i=1;i<=n;i++)    {        cin>>v>>p>>q;        if (q)        {                q=next[q];            int l=a[q][0];            for (int j=1;j<=l;j++)            {                    a[q][++a[q][0]]=a[q][j]+v*p;                c[q][a[q][0]]=c[q][j]+v;            }            ///cout<<l<<' '<<q<<endl;        }        else a[++tail][++a[tail][0]]=v*p,c[tail][1]=v,next[i]=tail;    }    for (int k=1;k<=tail;k++){//组数         for(int i=1;i<=a[k][0];i++){//分组物品个数             for (int j=m;j>=c[k][i];j--){//空间             if (dp[k][j]<max(dp[k-1][j],dp[k-1][j-c[k][i]]+a[k][i]))            dp[k][j]=max(dp[k-1][j],dp[k-1][j-c[k][i]]+a[k][i]);//状态转移            }        }    }    cout<<dp[tail][m];        return 0;     }

感觉洛谷有一个点数据错了,下下来数据自己演算也是500但是答案是700,一脸懵逼,对每个组012背包,还是比较简单的

1 0