1 条题解

  • 0
    @ 2025-10-16 9:54:54
    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    int main() 
    {
        int N, M; // N: 总预算,M: 主商品数量
        cin >> N >> M;
        
        // 存储每组商品(主件及其附件)的所有可能组合(花费,满意度)
        vector<vector<pair<int, int>>> groups;
        
        // 处理每个主商品
        for (int i = 0; i < M; i++) 
    	{
            int v, p, q; // v: 主件价格,p: 主件满意度,q: 附属商品数量
            cin >> v >> p >> q;
            
            vector<pair<int, int>> accessories; // 存储附属商品的价格和满意度
            for (int j = 0; j < q; j++) 
    		{
                int a, b; // a: 附属商品价格,b: 附属商品满意度
                cin >> a >> b;
                accessories.push_back({a, b});
            }
            
            // 生成当前主件的所有可能组合(包括不买附件、买一个附件、买两个附件等)
            vector<pair<int, int>> choices;
            int states = 1 << q; // 使用位运算表示所有可能的组合,每个位表示是否购买对应的附件
            for (int s = 0; s < states; s++)
    		{
                int total_cost = v;    // 总花费至少包括主件价格
                int total_value = p;   // 总满意度至少包括主件满意度
                
                // 遍历每个附件,根据位运算状态决定是否购买
                for (int k = 0; k < q; k++) 
    			{
                    if (s & (1 << k)) 
    				{ // 如果第k个附件被选中
                        total_cost += accessories[k].first;
                        total_value += accessories[k].second;
                    }
                }
                
                // 如果当前组合的花费不超过总预算,则将其加入可选组合
                if (total_cost <= N) 
    			{
                    choices.push_back({total_cost, total_value});
                }
            }
            
            // 将当前主件的所有组合加入组列表
            groups.push_back(choices);
        }
        
        // 动态规划数组,dp[j]表示花费j元能获得的最大满意度
        vector<int> dp(N + 1, 0);
        
        // 遍历每组商品
        for (size_t i = 0; i < groups.size(); i++) 
    	{
            // 从大到小遍历预算,避免重复选择同一组内的多个组合
            for (int j = N; j >= 0; j--)
    		{
                // 遍历当前组内的每个组合
                for (auto& choice : groups[i]) 
    			{
                    int cost = choice.first;
                    int value = choice.second;
                    // 如果当前预算j足够支付该组合的花费
                    if (j >= cost) 
    				{
                        // 更新dp[j]: 比较当前值和选择该组合后的值
                        dp[j] = max(dp[j], dp[j - cost] + value);
                    }
                }
            }
        }
        
        // 输出在总预算N下能获得的最大满意度
        cout << dp[N] << endl;
        
        return 0;
    }
    

    信息

    ID
    155
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者