【01背包 && 完全背包】高数Umaru系列(9)——哈士奇 && 小P的故事——神奇的Dota

高数Umaru系列(9)——哈士奇
Time Limit: 1000MS Memory Limit: 65536KB
Problem Description

由于高数巨养的喵星人太傲娇了,要天天吃新鲜猫粮而且还经常欺负高数巨,所以高数巨决定买几条哈士奇尝尝鲜。这天高数巨来到了二手狗市场买哈士奇,高数巨看完了所有的哈士奇,记下了每条哈士奇的价格,并根据对它们的好感程度给它们每只都赋予了一个萌值。高数现在手里有X元,她想通过购买若干条哈士奇来获得尽可能多的萌值。现在给定高数巨手里的钱X以及N条哈士奇的价格和萌值,求高数巨最多可获得多少萌值
Input

多组输入。

对于每组输入,第一行有两个整数N,X(1 < = N < = 100,1 < = X < = 1000),分别表示哈士奇的数量和高数巨的钱数

接下来的N行每行有两个整数Pi,Mi(1 < = Pi,Mi < = 100),分别表示第i条哈士奇的价格和萌值
Output

对于每组数据,输出一个整数,表示高数巨最多可以获得的萌值,每组输出占一行
Example Input

2 100
50 20
60 40
3 100
20 55
20 35
90 95
1 10
20 50

Example Output

40
95
0
学习背包,这里要推出一个思想,当你取到第N个背包,你有两种选择方式,一种是取,一种是不取,当你不取就和前面一样,当你取就等于这个背包的价格+上你前面的所以最容易想到的代码如下

#include<stdio.h>
#include<string.h>
int max(int a, int b)
{
    if(a < b) return b;
    else return a;
}
int main()
{
    int a[1015][105]; /*i表示钱,j表示*/
    int n, x, p[105], m[105], i, j;
    while(~scanf("%d %d", &n, &x))
    {
        memset(a, 0, sizeof(a));
        for(i = 1; i <= n; i++)
        {
            scanf("%d %d", &p[i], &m[i]);
        }
        for(i = 1; i <= x; i++)/*钱*/
        {
            for(j = 1; j <= n; j++)/*狗的数量*/
            {
                if(i >= p[j])
                {
                a[i][j] = max(a[i][j-1], a[i - p[j]][j - 1] + m[j]);}
                else
                {
                    a[i][j] = a[i][j-1];
                }
            }
        }
        printf("%d\n", a[x][n]);
    }
    return 0;
}

然而我们想要简便点,就得思考能不能直接一维数组处理,接下来的代码上面是二维数组下面是一维数组,为了方面你的理解,至于怎么想出来的我也不知道,但是你理解它为什么能代替二维数组就可以了。

/*#include<stdio.h>
#include<string.h>
int max(int a, int b)
{
    if(a < b) return b;
    else return a;
}
int main()
{
    int a[105][1015];
    int n, x, p[105], m[105], i, j;
    while(~scanf("%d %d", &n, &x))
    {
        memset(a, 0, sizeof(a));
        memset(p, 0, sizeof(p));
        memset(m, 0, sizeof(m));
        for(i = 1; i <= n; i++)
        {
            scanf("%d %d", &p[i], &m[i]);
        }
        for(i = 1; i <= n; i++)
        {
            for(j = 1; j <= x; j++)
            {
                if(j >= p[i])
                {
                a[i][j] = max(a[i - 1][j], a[i - 1][j - p[i]] + m[i]);}
                else
                {
                    a[i][j] = a[i - 1][j];
                }
            }
        }
        printf("%d\n", a[n][x]);
    }
    return 0;
}*/
#include<stdio.h>
#include<string.h>
int max(int a, int b)
{
    if(a < b) return b;
    else return a;
}
int main()
{
    int a[1015];
    int n, x, p[105], m[105], i, j;
    while(~scanf("%d %d", &n, &x))
    {
        memset(a, 0, sizeof(a));
        memset(p, 0, sizeof(p));
        memset(m, 0, sizeof(m));
        for(i = 1; i <= n; i++)
        {
            scanf("%d %d", &p[i], &m[i]);
        }
        for(i = 1; i <= n; i++)
        {
            for(j = x; j >= 1; j--)
            {
                if(j >= p[i])
                {
                a[j] = max(a[j], a[j - p[i]] + m[i]);}
            }
        }
        printf("%d\n", a[x]);
    }
    return 0;
}

如果物品取的次数不限,就是完全背包类型,循环变成1 to x,为什么得自己慢慢思考,真不好说出来来个完全背包的例子
小P的故事——神奇的Dota
Time Limit: 1000MS Memory Limit: 65536KB
Problem Description
小P非常喜欢玩dota,不分昼夜的玩
,结果他连做梦也都是里面的画面,一天晚上小P刚躺下就做了一个神奇的梦。。。
不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,只有一张钞票),为了防止自己在战斗中频繁的死掉,他决定给自己买一些道具,于是他来到了地精商店前.
死亡骑士:”我要买道具!”
地精商人:”我们这里有三种道具,血瓶150块一个,魔法药200块一个,无敌药水350块一个.”
死亡骑士:”好的,给我一个血瓶.”
说完他掏出那张N元的大钞递给地精商人.
地精商人:”我忘了提醒你了,我们这里没有找客人钱的习惯的,多的钱我们都当小费收了的,嘿嘿.”
死亡骑士:”……”
死亡骑士想,与其把钱当小费送个他还不如自己多买一点道具,反正以后都要买的,早点买了放在家里也好,但是要尽量少让他赚小费.
现在死亡骑士感觉自己的智商不够用所以希望小P帮他计算一下,最少他要给地精商人多少小费.但是小P的智商可是出了名的“不忍直视”啊,聪明非凡的你所以你能帮帮他吗?
Input
输入数据的第一行是一个整数T(1<=T<=100),代表测试数据的数量.然后是T行测试数据,每个测试数据只包含一个正整数N(1<=N<=10000),N代表死亡骑士手中钞票的面值.

注意:地精商店只有题中描述的三种道具.
Output
对于每组测试数据,请你输出死亡骑士最少要浪费多少钱给地精商人作为小费.

Example Input

2
380
200

Example Output

30
0

#include<stdio.h>
#include<string.h>
int max(int a, int b)
{
    if(a < b) return b;
    else return a;
}
int main()
{
    int a[10510];
    int n, i, j, t;
    int w[4], p[4];
    scanf("%d", &t);
    while(t--)
    {
        memset(a, 0, sizeof(a));
        p[1] = w[1] = 150;
        p[2] = w[2] = 200;
        p[3] = w[3] = 350;
        scanf("%d", &n);
        for(i = 1; i <= 3; i++)
        {
            for(j = 1; j <= n; j++)
            {
                if(j >= w[i])
                a[j] = max(a[j], a[j - w[i]] + p[i]);
            }
        }
        printf("%d\n", n - a[n]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值