完全背包

先说说动态规划吧,最重要的就是找转移方程(虽然我开始感觉自己没找,都是自己想的,但是回头看,只不过是脑子里找的,但是当时不认为那个是转移方程,多刷刷就会了)

背包问题这里就不讲了,网上找找就好啦

简单提一下优化,就是背包的d[i][j]可以优化为d[j],因为每一次都是递推,把所有的和所有累加的放进去,一个一维数组足矣。

 

讲完全背包之前,先讲一个完全背包退化版的问题,对理解完全背包很有帮助哦

在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法。请你编程序计算出共有多少种兑法。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1284

这个题其实用暴力也是可以的,但是为了学动态规划,就得用动态规划的思想想想

假如只有1分硬币,就是从第一个递推到第n个,假如只有2分、3分同理,转移方程是d[j]  = d[j] + d[j - i]。

#include <stdio.h>
int a[40000];
int main()
{
        int i = 0;
        int j = 0;
        a[0] = 1;
        for(i = 1;i <= 3;i++)
                for(j = i;j <= 40000;j++)
                a[j] += a[j -i];
        while(scanf("%d",&i) != EOF)
        printf("%d\n",a[i]);
        return 0;
}

 下来讲讲完全背包问题

设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于M,而价值的和为最大。

先说说最简单的方法把,把完全背包问题退化为背包问题就行了(^_^)

这种方法就是说,把每一个物品都乘上几次(肯定比最大载重小),让一个物品变成多个物品,然后按背包问题的思路就行了。

虽然这种方法也行,也是O(n * v),但是在常数意义上,就高很多了,所以还是用一般方法好点。

 

背包问题的转移方程:d[i][j] = max(d[i - 1][j],d[i - 1][j - v[i]] + w[j]);

意思就是每一个后面的都是d[i - 1][j]或者d[i - 1][j - v[i]] + w[j],然后无限下推,分成一个个自问题。

完全背包是每一个后面的都是前面所有的加上(自己*k)所有可能的,

#include "iostream"
#include "cstdio"
#include "cstring"
#include "cstdlib"
#include "cmath"

using namespace std;
int M,N;                //M是最大容量,M <= 200
int W[300],C[300];

int qq[200];            //从前到后遍历,该对应容量的最大价值
int main()
{
        memset(qq,0,sizeof(qq));
        memset(W,0,sizeof(W));
        memset(C,0,sizeof(C));
        scanf("%d%d",&M,&N);
        int i = 0;
        for(i = 0;i < N;i++)
        scanf("%d%d",&W[i],&C[i]);
        for(i = 0;i < N;i++)
        {
                if(qq[W[i]] <C[i])
                qq[W[i]] = C[i];
                int j = 0;
                for(j = 0;j <= M - W[i];j++)
                {
                        int abc = j + W[i];     //记录是否小于200
                        while(abc <= M)
                        {
                                //qq[j + W[i]] < qq[j] + c[i];
                                if(qq[abc] < (qq[abc-W[i]] + C[i]))
                                qq[abc] = qq[abc-W[i]] + C[i];
                                abc += W[i];
                        }
                }
        }
        int max = 0;
        for(i = 0;i <= M;i++)
        if(qq[i] > max)
        max = qq[i];
        cout << max << endl;
        return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值