动态规划3 背包总结及其优化

来源:互联网 发布:方正字体排查软件 编辑:程序博客网 时间:2024/06/02 06:18

一.01背包的一维空间优化

1.只定义一个一维数组来记录当前重量下的最大值情况不断更新(虽然优化了空间复杂度但是这样只能求出最大值而不能求出最优解)

2.核心算法:best[j]=best[j]>best[j-w[i]]+v[i]?best[j]:best[j-w[i]]+v[i];(放入还是不放入)

3.关于第二重循环(重量)为何逆序判断:我们来看二位递推公式:backpack[i][j]=backpack[i-1][j]>(backpack[i-1][j-wi[i]]+value[i])?backpack[i-1][j]:backpack[i-1][j-wi[i]]+value[i];

可以看出:f[i][j]的状态是由f[i-1][j]推出来的也就是说我们现在要求的状态是上一个已经存在的状态推出来的

<1>如果逆循环:从dp[C]开始,找dp[C-w[i]]来求dp[C],而dp[C-w[i]]是上一次已经存在的状态,所以符合二维递推,由已存在的上一状态来推下一状态。

<2>如果顺序循环:从dp[0]开始,把以前存在的状态都更新了,以后求的dp[C]是在更新了的状态下推出来的,所以肯定不对!

综上:第二重循环选择逆序!!

4.代码:

#include <stdio.h>#include<string.h>int w[1000],v[1000];int best[1000];int main(){    int n,C;    while(scanf("%d%d",&n,&C)!=EOF)    {        int i,j,t;        memset(best,0,sizeof(best));        for(i=1; i<=n; i++)            scanf("%d",&w[i]);        for(i=1; i<=n; i++)            scanf("%d",&v[i]);        for(i=1; i<=n; i++)        {            for(j=C; j>=w[i]; j--)//逆序!j>=w[i]使j-w[i]>=0而有意义            {                 best[j]=best[j]>best[j-w[i]]+v[i]?best[j]:best[j-w[i]]+v[i];            }        }        printf("%d\n",best[C]);    }    return 0;}

二.完全背包解析及其优化

1.题意:在01背包基础上增加了有无限多个物品

2.解法一:三重循环枚举物品个数情况

代码:

#include <stdio.h>#include<string.h>int w[1000],v[1000];int best[1000][1000];int main(){    int n,C;    while(scanf("%d%d",&n,&C)!=EOF)    {        int i,j,t;        memset(best,0,sizeof(best));        for(i=1; i<=n; i++)            scanf("%d",&w[i]);        for(i=1; i<=n; i++)            scanf("%d",&v[i]);        for(i=1; i<=n; i++)        {            for(j=0; j<=C; j++)            {                int k=j/w[i];                for(t=0; t<=k; t++)//枚举物品个数                {                    best[i][j]=best[i][j]>best[i-1][j-t*w[i]]+t*v[i]?best[i][j]:best[i-1][j-t*w[i]]+t*v[i];//**                }            }        }        printf("%d\n",best[n][C]);    }    return 0;}

注:**处一个方程原因:1.当j<w[i]也就是该物品放不进去的时候:k=0,best[i][j]=best[i][j]>best[i-1][j]?best[i][j]:best[i-1][j];符合放不进去的时候情况,而且就判断这一次和不判一样
2.当j>=w[i]的时候,也就是可以放,这时候选择放还是不放,不放k=0:同一,符合best[i][j]=best[i-1][j];放k>0,判断最大也符合,并不断更新
3.综上一个方程即可,不用再加判断条件。
 


解法二:优化时间复杂度减少循环

1.注:由各种画图实验计算得:在best[i][j]的选择k种(k>=1)情况计算中,与在best[i][j-w[i]]的计算中选择k-1个情况是相同的,所以best[i][j]的递推中k>=1部分情况早已经在best[i][j-w[i]]中计算完了,best[i][j-w[i]]就是best[i][j]当k>=1时候的最大值,所以用其比较当k=0也就是不放的时候大小取最大即可。

2.代码:

#include <stdio.h>#include<string.h>int w[1000],v[1000];int best[1000][1000];int main(){    int n,C;    while(scanf("%d%d",&n,&C)!=EOF)    {        int i,j,t;        memset(best,0,sizeof(best));        for(i=1; i<=n; i++)            scanf("%d",&w[i]);        for(i=1; i<=n; i++)            scanf("%d",&v[i]);        for(i=1; i<=n; i++)        {            for(j=0; j<=C; j++)            {                if(j<w[i])                    best[i][j]=best[i-1][j];//不能放                else                    best[i][j]=best[i-1][j]>best[i][j-w[i]]+v[i]?best[i-1][j]:best[i][j-w[i]]+v[i];//放还是不放            }        }        printf("%d\n",best[n][C]);    }    return 0;}


解法三:空间优化
1.v变化的区间是顺序循环的原因:完全背包的特点是每种物品可选无限件,在求解加选第i种物品带来的收益f[i][v]时,在状态f[i][v-c[i]]中已经尽可能多的放入物品i了,此时在f[i][v-c[i]]的基础上,我们可以再次放入一件物品i,此时也是在不超过背包容量的基础下,尽可能多的放入物品i。
2.代码:

#include <stdio.h>#include<string.h>int w[1000],v[1000];int best[1000];int main(){    int n,C;    while(scanf("%d%d",&n,&C)!=EOF)    {        int i,j,t;        memset(best,0,sizeof(best));        for(i=1; i<=n; i++)            scanf("%d",&w[i]);        for(i=1; i<=n; i++)            scanf("%d",&v[i]);        for(i=1; i<=n; i++)        {            for(j=w[i]; j<=C; j++)//注意区间!!            {                best[j]=best[j]>best[j-w[i]]+v[i]?best[j]:best[j-w[i]]+v[i];            }        }        printf("%d\n",best[C]);    }    return 0;}


以上:背包问题。

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 钅部首的字 带钅字旁的女孩名字 钅监拼音怎么打 钅之旁的字 钅字旁的男孩名字大全 带钅字旁寓意好的字 带钅的字 钅字旁的男孩名 钅字旁的字适合女孩 带钅部首的吉祥字 带钅字旁的男孩名字 钅字旁的字哪些寓意好 钅字旁的字有哪些字 钅字旁的字有哪些 带钅字旁的字 钅是什么偏旁 钆怎么读 氧化钆价格 钇怎么读 钇字起名代表什么意思 钇铝石榴石 针眼 v脸针 眼针 破伤风针 破伤风针多少钱 屁股针 鬼针草 破伤风针什么时候打 一针见血 预防针 针眼图片 针的拼音 提升针 瘦下巴针多少钱 美白针针多少钱 整形针