AI 刷题2 饭馆菜品选择问题 题解 | 豆包MarsCode AI刷题

37 阅读3分钟

菜品选择最优化问题深入分析

问题描述

小C在餐厅面临选择菜品的问题,目标是在特定条件下最小化她所点菜品的总价格。具体条件包括:点菜的总数(k),其中含蘑菇的菜品数不超过(m)。此问题是一个典型的优化问题,其复杂性来自于同时满足多个约束条件。

解题思路

算法设计

这个问题可以看作是一个有条件的最小化背包问题,其中每种菜品可以看作一个物品,菜品价格看作成本,含蘑菇与否看作是一个额外的属性约束。我们需要从菜品中选择若干个以达到最小化总成本的目的,同时不超过含蘑菇菜品的最大数量。

动态规划方法

动态规划是解决此类问题的有效工具,特别是当问题涉及到优化决策和多阶段决策问题时。定义状态dp[i][j][l]表示在考虑前i个菜品时,选择了j道菜,其中恰好有l道含蘑菇的菜的最小总价格。初始状态和状态转移方程的设计是解决问题的关键。

状态转移
  • 初始状态dp[0][0][0] = 0,即没有菜时,成本为0。
  • 状态转移方程
    • 如果当前菜不含蘑菇(s[i] == '0'),则dp[i][j][l] = min(dp[i-1][j][l], dp[i-1][j-1][l] + a[i])
    • 如果当前菜含蘑菇(s[i] == '1'),则dp[i][j][l] = min(dp[i-1][j][l], dp[i-1][j-1][l-1] + a[i])(此处需保证l > 0
边界考虑
  • 无法满足选择要求时,应输出-1
  • 循环结束后检查dp[n][k][0]dp[n][k][m]中的最小值,得到最终结果。

复杂度分析

动态规划的时间复杂度为O(n*k*m),其中n是菜品总数,k是需要选择的菜品数,m是含蘑菇菜品的最大数目。这种复杂度对于中等规模的数据是可接受的。

特殊情况处理

  • 如果km为0,需要单独处理。
  • 如果所有菜品都含蘑菇而m小于k,则无解。

C++实现

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

int solution(const string& s, const vector<int>& prices, int m, int k) {
    int n = s.size();
    vector<vector<int>> dp(k+1, vector<int>(m+1, INT_MAX));
    dp[0][0] = 0;

    for (int i = 0; i < n; ++i) {
        for (int j = k; j > 0; --j) {
            for (int l = m; l >= 0; --l) {
                if (s[i] == '0' && dp[j-1][l] != INT_MAX) {
                    dp[j][l] = min(dp[j][l], dp[j-1][l] + prices[i]);
                } else if (s[i] == '1' && l > 0 && dp[j-1][l-1] != INT_MAX) {
                    dp[j][l] = min(dp[j][l], dp[j-1][l-1] + prices[i]);
                }
            }
        }
    }

    int result = INT_MAX;
    for (int l = 0; l <= m; ++l) {
        result = min(result, dp[k][l]);
    }
    return result == INT_MAX ? -1 : result;
}

int main() {
    cout << solution("001", {10, 20, 30}, 1, 2) << endl; // Outputs 30
    cout << solution("111", {10, 20, 30}, 1, 2) << endl; // Outputs -1
    cout << solution("0101", {5, 15, 10, 20}, 2, 3) << endl; // Outputs 30
    return 0;
}

结论

通过动态规划方法,我们能有效解决含有多重约束条件的优化问题。这种方法不仅适用于理论模型,还可扩展到实际应用中,如资源分配、预算规划等领域。