C语言-算法-背包

[USACO07DEC] Charm Bracelet S(01背包)

题目描述

Bessie has gone to the mall’s jewelry store and spies a charm bracelet. Of course, she’d like to fill it with the best charms possible from the N (1 ≤ N ≤ 3,402) available charms. Each charm i in the supplied list has a weight Wi (1 ≤ Wi ≤ 400), a ‘desirability’ factor Di (1 ≤ Di ≤ 100), and can be used at most once. Bessie can only support a charm bracelet whose weight is no more than M (1 ≤ M ≤ 12,880).

Given that weight limit as a constraint and a list of the charms with their weights and desirability rating, deduce the maximum possible sum of ratings.

N N N 件物品和一个容量为 M M M 的背包。第 i i i 件物品的重量是 W i W_i Wi,价值是 D i D_i Di。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。

输入格式

* Line 1: Two space-separated integers: N and M

* Lines 2…N+1: Line i+1 describes charm i with two space-separated integers: Wi and Di

第一行:物品个数 N N N 和背包大小 M M M

第二行至第 N + 1 N+1 N+1 行:第 i i i 个物品的重量 W i W_i Wi 和价值 D i D_i Di

输出格式

* Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints

输出一行最大价值。

样例 #1

样例输入 #1

4 6
1 4
2 6
3 12
2 7

样例输出 #1

23

代码实现

#include <stdio.h>
int max(int a, int b); // 用于判断两个数的大小的函数
#define MAX 30000
int N, M;
int W[MAX], D[MAX];
int dp[MAX]; // dp[j]表示总重量不超过j时的最大价值

int main()
{
    int i, j;
    scanf("%d %d", &N, &M);

    for (i = 1; i <= N; i++)
    {
        scanf("%d %d", &W[i], &D[i]);
    }
    for (i = 1; i <= N; i++) // 用动态规划来计算最大值
    {
         // 如果当前物品可以放入背包,那么尝试放入,并更新dp数组
        for (j = M; j >= W[i]; j--)
        {
            dp[j] = max(dp[j], dp[j - W[i]] + D[i]);
        }
    }
    printf("%d\n", dp[M]); // 输出背包能装入的最大价值
    return 0;
}

int max(int a, int b) // 用于判断两个数的大小的函数
{
    if (a > b)
    {
        return a;
    }
    else
    {
        return b;
    }
}

A - Bone Collector

题目描述

许多年前,在泰迪的家乡,有一个被称为“骨头收集者”的人。这个人喜欢收集各种骨头,比如狗的、牛的,甚至还去过坟墓……
骨头收集者有一个容积为V的大袋子,在他收集的过程中有很多骨头,显然,不同的骨头有不同的价值和不同的体积,现在给出每个骨头的价值,请你计算出骨头收集者能够获得的最大总价值?

输入

第一行包含一个整数T,表示案例的数量。
接下来是T个案例,每个案例包括三行,第一行包含两个整数N,V,(N <= 1000, V <= 1000),表示骨头的数量和他的袋子的容积。第二行包含N个整数,表示每个骨头的价值。第三行包含N个整数,表示每个骨头的体积。

输出

每行输出一个整数,表示最大的总价值(这个数字将小于231)。

样例

Input

在这里插入图片描述

Output

在这里插入图片描述

代码

#include <stdio.h>
int max(int a, int b);
#define MAX 2000

int main()
{
    int T, N, V, i, j, k;
    int D[MAX], v[MAX], dp[MAX];
    scanf("%d", &T); // 数量

    for (i = 1; i <= T; i++)
    {
        scanf("%d %d", &N, &V); // 数量和袋子的容积
        for (j = 1; j <= N; j++)
        {
            scanf("%d", &D[j]); // 价值
        }
        for (k = 1; k <= N; k++)
        {
            scanf("%d", &v[k]); // 体积
        }
        for (i = 0; i <= V; i++)
        {
            dp[i] = 0; // 初始化dp数组
        }
        for (i = 1; i <= N; i++)
        {
            for (j = V; j >= v[i]; j--)
            {
                dp[j] = max(dp[j], dp[j - v[i]] + D[i]);
            }
        }
        printf("%d\n", dp[V]);
    }
    return 0;
}

int max(int a, int b)
{
    if (a > b)
    {
        return a;
    }
    else
    {
        return b;
    }
}

[NOIP2006 普及组] 开心的金明(01背包)

题目描述

金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过 N N N 元钱就行”。今天一早金明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的 N N N 元。于是,他把每件物品规定了一个重要度,分为 5 5 5 等:用整数 1 − 5 1-5 15 表示,第 5 5 5 等最重要。他还从因特网上查到了每件物品的价格(都是整数元)。他希望在不超过 N N N 元(可以等于 N N N 元)的前提下,使每件物品的价格与重要度的乘积的总和最大。

设第 j j j件物品的价格为 v j v_j vj,重要度为 w j w_j wj,共选中了 k k k 件物品,编号依次为 j 1 , j 2 , … , j k j_1,j_2,…,j_k j1,j2,,jk,则所求的总和为:

v j 1 × w j 1 + v j 2 × w j 2 … + v j k × w j k v_{j_1} \times w_{j_1}+v_{j_2} \times w_{j_2} …+v_{j_k} \times w_{j_k} vj1×wj1+vj2×wj2+vjk×wjk

请你帮助金明设计一个满足要求的购物单。

输入格式

第一行,为 2 2 2 个正整数,用一个空格隔开: n , m n,m n,m n < 30000 , m < 25 n<30000,m<25 n<30000,m<25)其中 n n n 表示总钱数, m m m 为希望购买物品的个数。

从第 2 2 2 行到第 m + 1 m+1 m+1 行,第 j j j 行给出了编号为 j − 1 j-1 j1 的物品的基本数据,每行有 2 2 2 个非负整数 v , p v,p v,p(其中 v v v 表示该物品的价格 ( v ≤ 10000 ) (v \le 10000) (v10000) p p p 表示该物品的重要度( 1 ≤ p ≤ 5 1\le p\le5 1p5)。

输出格式

1 1 1 个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值( < 100000000 <100000000 <100000000)。

样例 #1

样例输入 #1

1000 5
800 2
400 5
300 5
400 3
200 2

样例输出 #1

3900

代码

#include <stdio.h>
#include <string.h>
int max(int a, int b);
#define MAX 40000

int main()
{
    int n, m, i, j, v[MAX], p[MAX], a[MAX]; // 数组a表示每种物品的价格和重要度乘积
    long long dp[MAX];
    memset(dp, 0, sizeof(dp)); // 初始化,dp表示不超过总钱数的物品的价格与重要度乘积的总和的最大值
    scanf("%d %d", &n, &m); // 总钱数和希望购买物品的个数

    for (i = 1; i <= m; i++)
    {
        scanf("%d %d", &v[i], &p[i]); // 物品的价格和重要程度
        a[i] = v[i] * p[i];
    }
    for (i = 1; i <= m; i++)
    {
        for (j = n; j >= v[i]; j--)
        {
            dp[j] = max(dp[j], dp[j - v[i]] + a[i]);
        }
    }
    printf("%lld", dp[n]);
    return 0;
}

int max(int a, int b)
{
    if (a > b)
    {
        return a;
    }
    else
    {
        return b;
    }
}

NASA的食物计划(二维费用背包)

题目背景

NASA(美国航空航天局)因为航天飞机的隔热瓦等其他安全技术问题一直大伤脑筋,因此在各方压力下终止了航天飞机的历史,但是此类事情会不会在以后发生,谁也无法保证。所以,在遇到这类航天问题时,也许只能让航天员出仓维修。但是过多的维修会消耗航天员大量的能量,因此 NASA 便想设计一种食品方案,使体积和承重有限的条件下多装载一些高卡路里的食物。

题目描述

航天飞机的体积有限,当然如果载过重的物品,燃料会浪费很多钱,每件食品都有各自的体积、质量以及所含卡路里。在告诉你体积和质量的最大值的情况下,请输出能达到的食品方案所含卡路里的最大值,当然每个食品只能使用一次。

输入格式

第一行 2 2 2 个整数,分别代表体积最大值 h h h 和质量最大值 t t t

第二行 1 1 1 个整数代表食品总数 n n n

接下来 n n n 行每行 3 3 3 个数 体积 h i h_i hi,质量 t i t_i ti,所含卡路里 k i k_i ki

输出格式

一个数,表示所能达到的最大卡路里(int 范围内)

样例 #1

样例输入 #1

320 350
4
160 40 120
80 110 240
220 70 310
40 400 220

样例输出 #1

550

提示

对于 100 % 100\% 100% 的数据, h , t , h i , t i ≤ 400 h,t,h_i,t_i \le 400 h,t,hi,ti400 n ≤ 50 n \le 50 n50 k i ≤ 500 k_i \le 500 ki500

代码

#include <stdio.h>
int max(int a, int b);
#define MAX 1000
int dp[MAX][MAX];

int main()
{
    int h, t, n, i, j, k;
    int H[MAX], T[MAX], K[MAX];
    scanf("%d %d", &h, &t); // 体积最大值和质量最大值
    scanf("%d", &n); // 食品总数

    for (i = 1; i <= n; i++)
    {
        scanf("%d %d %d", &H[i], &T[i], &K[i]); // 体积,质量,卡路里
    }
    for (i = 1; i <= n; i++) // 动态规划
    {
        for (j = h; j >= H[i]; j--)
        {
            for (k = t; k >= T[i]; k--)
            {
                dp[j][k] = max(dp[j][k], dp[j - H[i]][k - T[i]] + K[i]);
            }
        }
    }
    printf("%d\n", dp[h][t]);

    return 0;
}

int max(int a, int b)
{
    if (a > b)
    {
        return a;
    }
    else
    {
        return b;
    }
}
  • 29
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值