【算法题】买糖果

买糖果

某糖果公司专门生产儿童糖果,它最受儿童欢迎的糖果有A1、A2两个序列,均采用盒式包装。包装好的A1类糖果体积为一个存储单位,而包装好的A2类糖果体积正好是A1类的两倍。

这两类糖果之所以广受儿童欢迎,是因为糖果中含有公司独家研发的魔幻因子。A1或A2序列中的糖果,看起来包装可能是一样的,但因为其中的魔幻因子含量不同被细分为不同的产品。

临近传统节日,公司的糖果供不应求。作为一个精明的糖果分销商,小东希望能够借此大赚一笔,于是带着现金开着货车来公司提货。货车的容量是确定的,小东希望采购的糖果能够尽可能装满货车,且糖果的魔幻因子总含量最高。只要不超出货车容量,糖果总可以装入货车中。

小东希望你能帮她解决这一问题。

输入
输入中有多组测试数据。每组测试数据的第一行有两个整数n和v,1<=n<=10^5, 1<=v<=10^9,n为可供选购糖果数量,v为货车的容量。随后n行为糖果的具体信息,第一行编号为1,第二行编号为2,以此类推,最后一行编号为n。每行包含两个整数ti和pi,1<=ti<=2, 1<=pi<=10^4,ti为糖果所属的序列,1为A1、2为A2,pi则是其中的魔幻因子含量。

  • 样例输入
    3 2
    1 2
    2 7
    1 3

输出
每组测试数据,先在单独的一行中输出能采购的糖果中的魔幻因子最高含量,之后在单独的行中按编号从小到大的顺序输出以空格分隔的糖果编号,若有多组糖果组合均能满足要求,输出编号最小的组。若没有糖果能够满足要求,则在第一行中输出0,第二行输出“No”。

  • 样例输出
    7
    2

分析:01背包问题,动态规划

使用 dp[i][j] 表示前 i 个糖果在 j 容量下可得到的最大魔幻因子含量

dp[i][j]=maxdp[i1][j]dp[i1][jvolume[i]]+value[i]

注意事项:

  • 要单独考虑车容量大于所有糖果体积和情况
  • 多组输入、多组输出、容器清空
  • v的数据过大 ,需要long long类型

  • vector.size()返回类型为无符号整型:

    for (int j = printvec.size() - 1; j >= 0; j–)

    不能写成

    for (auto j = printvec.size() - 1; j >= 0; j–)


#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
//#define debug_
int n; long long v;
vector<int> volum;
vector<int> value;

void func()
{
    vector<vector<int>> dp;
    vector<int> tmp(v + 1);

    dp.resize(n + 1, tmp);

    int lhs, rhs;

    for (auto i = 0; i < dp.size(); ++i)
    {
        for (auto j = 0; j < dp[i].size(); ++j)
        {
            lhs = 0;
            rhs = 0;
            if (i - 1 >= 0)
            {
                lhs = dp[i - 1][j];
            }
            if (i - 1 >= 0 && j - volum[i - 1] >= 0)
            {
                rhs = dp[i - 1][j - volum[i - 1]] + value[i - 1];
            }

            dp[i][j] = max(lhs, rhs);
        }
    }
    cout << dp[n][v] << endl;
    vector<int> printvec;
    if (dp[n][v] == 0)
    {
        cout << "No" << endl;
    }
    else
    {
        int i = n, j = v;
        while (i)
        {
            if (dp[i][j] != dp[i - 1][j])
            {
                printvec.push_back(i);
                j = j - volum[i - 1];
            }
            i--;
        }
        for (int j_ = printvec.size() - 1; j_ >= 0; j_--)
        {
            cout << printvec[j_] << ' ';
        }
        cout << endl;
    }
}


int main()
{

#ifdef debug_
    n = 3;
    v = 2;
    volum.push_back(1);
    volum.push_back(1);
    volum.push_back(1);
    value.push_back(2);
    value.push_back(2);
    value.push_back(3);
    func();
#else
    while (cin >> n)
    {
        cin >> v;
        long long max_volume(0);
        volum.clear();
        value.clear();
        volum.resize(n);
        value.resize(n);
        for (auto i = 0; i < n; ++i)
        {
            cin >> volum[i];
            cin >> value[i];
            max_volume += volum[i];
        }
        if (max_volume <= v)
        {
            cout << accumulate(value.begin(), value.end(), 0) << endl;
            for (auto i = 1; i < n + 1; ++i)
            {
                cout << i << " ";
            }
            cout << endl;
        }
        else
        {
            func();
        }
    }
#endif
    return 0;

}

你可能感兴趣的:(赛码网输入输出参考,京东2016编程题,动态规划)