第八次总结 背包(一)

这一周主要是看了一下背包问题的知识点。在学习中知道除了简单的背包外还有完全背包,多重背包还有分组的背包问题,只可惜我还没有看完。就先简单的整理几个题目吧。
如有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
基本思路:
特点:每种物品仅有一件,可以选择放或不放。

状态转移方程状态转移方程:f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
其中f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。

一、简单的背包问题
如上,循环次序从大到小。
Charm Bracelet
有N件物品和一个容量为V的背包。第i件物品的费用是c,价值是w。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
初始化细节:
若要求恰好装满背包,初始化时除了f[0]为0其它f[1…V]均设为-∞
若没有要求必须把背包装满,初始化时将f[0…V]全部设为0
代码如下:

#include<iostream>
using namespace std;
#define MAX_N 3500
#define MAX_V 20000
struct good
{
    int c;
    int w;
}goods[MAX_N];
int main()
{
    int i,j;
    int n,v;
    int f[MAX_V];

while(cin>>n>>v)
    {
        for(i=0;i<=v;i++)f[i]=0;
        for(i=0;i<n;i++)cin>>goods[i].c>>goods[i].w;
        for(i=0;i<n;i++)
        {
            for(j=v;j>=goods[i].c;j--)
            {
                   if(f[j]<f[j-goods[i].c]+goods[i].w)
                   f[j]=f[j-goods[i].c]+goods[i].w;
            }
        }
        cout<<f[v]<<endl;
    }
    return 0;
}


二、完全背包
循环次序从小到大。
有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。需要先转化为01背包,考虑到第i种物品最多选V/c[i]件,于是可以把第i种物品转化为V/c[i]件费用及价值均不变的物品,然后求解这个01背包问题 。
题目
1.有n种食物。每种食物含有的热量和带来的幸福感分别为a[i]和b[i]。一个人每天摄入的热量不超过m。求在不超过一天热量摄入量前提下,可获得的最多幸福感是多少。

#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
int dp[100006];
int main()
{
    int t,n;
    while(scanf("%d",&n))
    {
        memset(dp,0,sizeof(dp));
        int i,j,m;
        int a[105],b[105];
        for(i = 0; i<t; i++)
            scanf("%d%d",&a[i],&b[i]);
        scanf("%d",&m);
        for(i = 0; i<n; i++) //状态转移方程
        {
            for(j = a[i]; j<=m; j++)
            {
                dp[j] = max(dp[j],dp[j-a[i]]+b[i]);
            }
        }
printf("%d\n",dp[m]);
    }
    return 0;
}

2、给一个储钱罐,e罐子重e,装满后重f,有n种硬币,每种重w[i],价值为p[i].问最少用多少钱可以装满罐子。如果不能装满输出This is impossible.
这个就是一个很明显的简单完全背包,只是和平时不同的是,他是求最小价值而不是最大。而且背包不是随意装而是要装满。

#include <iostream>
#include <string.h>
const int INF = 1000000000;
int  f[10010];
int main()
{
    int E, F, W, T, n, p, w,i , j;
    scanf("%d\n",&T);
while(T--)
    {
        scanf("%d%d",&E,&F); W = F - E;
        scanf("%d",&n);
        for(i=1; i<=W; i++) f[i] = INF;
        f[0] = 0;
        for(i=0; i<n; i++)
        {
            scanf("%d%d",&p, &w);
            for(j=w; j<=W; j++)
            if(f[j]>f[j-w]+p)
                f[j] = f[j-w]+p;
        }
        if(f[W]!=INF)
        printf("The minimum amount of money in the piggy-bank is %d.\n",f[W]);
        else
            printf("This is impossible.\n");
    }
    return 0;
}

后面还有多重和分组的背包问题未看完,我会补充在下一周的总结中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值