奇安信多重背包笔试题

原题

有一个人可以洞察市场动向,他能知道10天后商品的价格,请问如何分配其本金才能将其收益最大化?
Input:
总计本金:x
商品种类:m
各种类的价格:a, b, c, ...
各种类的限购数量:1, 2, 3, ...
各种类10天后的价格:A, B, C, ...
Output:
这个人10天后的总金

示例:
11
2
6 5
3 2
5 3
输出:
18

1.零一背包

参考这位大佬,强烈建议阅读;
图片说明
解答:

#include <vector>
#include <iostream>
#include <string>
#include <algorithm>


using namespace std;


class Stuff
{
public:
    Stuff(const initializer_list<int>& li) {
        auto it = li.begin();
        weight = *it++;
        value = *it;
    }
    int weight;
    int value;

    int operator<(const Stuff& stuff) {
        return weight < stuff.weight;
    }

};

std::ostream& operator<<(std::ostream &st, const Stuff& stuff) {
    st << "(" << stuff.weight << "," << stuff.value << ") ";
    return st;
}

int main() {
    int package_size = 15;
    vector<Stuff> stuffs({{12,4}, {2,2}, {1,1}, {4,10}, {1,2}});
    vector<int> dp(package_size+1);

    for(int i=0, len=stuffs.size(); i < len; ++i) {
        for(int j=package_size; j>=stuffs[i].weight; --j) {
            // 状态转移方程
            dp[j] = max(dp[j], dp[j-stuffs[i].weight] + stuffs[i].value);
        }
    }

    for(auto& val : dp) {
        cout << val << " ";
    }
    cout << endl;
}

2.完全背包

完全背包(unbounded knapsack problem)与01背包不同就是每种物品可以有无限多个:一共有N种物品,每种物品有无限多个,第i(i从1开始)种物品的重量为w[i],价值为v[i]。在总重量不超过背包承载上限W的情况下,能够装入背包的最大价值是多少?

#include <vector>
#include <iostream>
#include <string>
#include <algorithm>


using namespace std;


class Stuff
{
public:
    Stuff(const initializer_list<int>& li) {
        auto it = li.begin();
        weight = *it++;
        value = *it;
    }
    int weight;
    int value;

    int operator<(const Stuff& stuff) {
        return weight < stuff.weight;
    }

};

std::ostream& operator<<(std::ostream &st, const Stuff& stuff) {
    st << "(weight=" << stuff.weight << ", value=" << stuff.value << ") ";
    return st;
}

int main() {
    int package_size = 15;
    vector<Stuff> stuffs({{12,4}, {2,2}, {1,1}, {4,10}, {1,2}});
    vector<int> dp(package_size+1);
    sort(stuffs.begin(), stuffs.end());
    for(auto& val : stuffs)
        cout << val << endl;

    for(int i=0, len=stuffs.size(); i < len; ++i) {
        for(int j=stuffs[i].weight; j<=package_size; ++j) {
            dp[j] = max(dp[j], dp[j-stuffs[i].weight] + stuffs[i].value);
        }
    }

    for(auto& val : dp) {
        cout << val << " ";
    }
    cout << endl;
}

这里只修改了for循环中dp的更新策略,第一层是对于所有物品的遍历,第二层是对所有背包大小的遍历,因为物品不限量,所以物品购买后的状态应该叠加在上一个状态上,因此对j采用了前序遍历的方式。

3.多重背包

多重背包(bounded knapsack problem)与前面不同就是每种物品是有限个:一共有N种物品,第i(i从1开始)种物品的数量为n[i],重量为w[i],价值为v[i]。在总重量不超过背包承载上限W的情况下,能够装入背包的最大价值是多少?

#include <vector>
#include <iostream>
#include <string>
#include <algorithm>


using namespace std;


class Stuff
{
public:
    Stuff(const initializer_list<int>& li) {
        auto it = li.begin();
        weight = *it++;
        value = *it++;
        if(it != li.end())
            limit=*it;
    }
    int weight;
    int value;
    int limit = 1;

    int operator<(const Stuff& stuff) {
        return weight < stuff.weight;
    }
};

std::ostream& operator<<(std::ostream &st, const Stuff& stuff) {
    st << "(weight=" << stuff.weight << ", value=" << stuff.value
       << (stuff.limit <= 1 ? "" : string(", limit=") + to_string(stuff.limit))
       << ") ";
    return st;
}

int main() {
    int package_size = 15;
    vector<Stuff> stuffs({{12, 4,  3},
                          {2,  2,  6},
                          {1,  1,  3},
                          {4,  10, 2},
                          {1,  2,  2}});
    vector<int> dp(package_size+1);
    sort(stuffs.begin(), stuffs.end());
    for(auto& val : stuffs)
        cout << val << endl;

    for(int i=0, len=stuffs.size(); i < len; ++i) {
        const Stuff& s = stuffs[i];
        for(int j=package_size; j>=s.weight; --j) {
            for(int k=1; k<s.limit; ++k){
                dp[j] = max(dp[j], dp[j-s.weight] + s.value * k);
            }
        }
    }

    for(auto& val : dp) {
        cout << val << " ";
    }
    cout << endl;
}

至此,背包问题完结。

笔试题解

已知商品的现价为A,10天后的价格为B,则利润value=B-A,限购数量为limit。
已知value, limit, total_price,则可转化为多重背包问题,代入求解即可。

全部评论

相关推荐

05-20 13:59
门头沟学院 Java
米黑子米黑子:你这个成绩不争取下保研?
点赞 评论 收藏
分享
06-13 17:33
门头沟学院 Java
顺序不记了,大致顺序是这样的,有的相同知识点写分开了1.基本数据类型2.基本数据类型和包装类型的区别3.==和equals区别4.ArrayList与LinkedList区别5.hashmap底层原理,put操作时会发生什么6.说出几种树型数据结构7.B树和B+树区别8.jvm加载类机制9.线程池核心参数10.创建线程池的几种方式11.callable与runnable区别12.线程池怎么回收线程13.redis三剑客14.布隆过滤器原理,不要背八股,说说真正使用时遇到了问题没有(我说没有,不知道该怎么回答了)15.堆的内存结构16.自己在写项目时有没有遇见过oom,如何处理,不要背八股,根据真实经验,我说不会17.redis死锁怎么办,watchdog机制如何发现是否锁过期18.如何避免redis红锁19.一个表性别与年龄如何加索引20.自己的项目的QPS怎么测的,有没有真正遇到大数量表21.说一说泛型22.springboot自动装配原理23.springmvc与springboot区别24.aop使用过嘛?动态代理与静态代理区别25.spring循环依赖怎么解决26.你说用过es,es如何分片,怎么存的数据,1000万条数据怎么写入库中27.你说用limit,那么在数据量大之后,如何优化28.rabbitmq如何批次发送,批量读取,答了延迟队列和线程池,都不对29.计网知不知道smtp协议,不知道写了对不对,完全听懵了30.springcloud知道嘛?只是了解反问1.做什么的?短信服务,信息量能到千万级2.对我的建议,基础不错,但是不要只背八股,多去实际开发中理解。面试官人不错,虽然没露脸,但是中间会引导我回答问题,不会的也只是说对我要求没那么高。面完问我在济宁生活有没有困难,最快什么时候到,让人事给我聊薪资了。下午人事打电话,问我27届的会不会跑路,还在想办法如何使我不跑路,不想扣我薪资等。之后我再联系吧,还挺想去的😭,我真不跑路哥😢附一张河科大幽默大专图,科大就是大专罢了
查看30道真题和解析
点赞 评论 收藏
分享
评论
点赞
3
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务