解题思路

使用动态规划求解:

  1. 状态定义: 表示前 个菜品中,是否能凑出总价
  2. 状态转移:
    • 不选第 个菜:
    • 选第 个菜:
  3. 从满足条件的最小价格开始向上找第一个可以凑出的价格

代码

def solve():
    # 读取输入
    n, x = map(int, input().split())
    prices = list(map(int, input().split()))
    
    # 初始化dp数组
    dp = [[False] * 10001 for _ in range(n + 1)]
    dp[0][0] = True
    
    # 动态规划
    for i in range(n):
        for j in range(10001):
            # 不选第i个菜
            dp[i + 1][j] = dp[i][j]
            # 选第i个菜
            if j >= prices[i]:
                dp[i + 1][j] |= dp[i][j - prices[i]]
    
    # 从满足条件的最小价格开始找
    for total in range(x, 10001):
        if dp[n][total]:
            print(total)
            break

if __name__ == "__main__":
    solve()
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        // 读取输入
        int n = sc.nextInt();
        int x = sc.nextInt();
        int[] prices = new int[n];
        for (int i = 0; i < n; i++) {
            prices[i] = sc.nextInt();
        }
        
        // 初始化dp数组
        boolean[][] dp = new boolean[n + 1][10001];
        dp[0][0] = true;
        
        // 动态规划
        for (int i = 0; i < n; i++) {
            for (int j = 0; j <= 10000; j++) {
                // 不选第i个菜
                dp[i + 1][j] = dp[i][j];
                // 选第i个菜
                if (j >= prices[i]) {
                    dp[i + 1][j] |= dp[i][j - prices[i]];
                }
            }
        }
        
        // 从满足条件的最小价格开始找
        for (int total = x; total <= 10000; total++) {
            if (dp[n][total]) {
                System.out.println(total);
                break;
            }
        }
    }
}
#include <iostream>
#include <vector>
using namespace std;

int main() {
    // 读取输入
    int n, x;
    cin >> n >> x;
    vector<int> prices(n);
    for (int i = 0; i < n; i++) {
        cin >> prices[i];
    }
    
    // 初始化dp数组
    vector<vector<int>> dp(n + 1, vector<int>(10001, 0));
    dp[0][0] = 1;
    
    // 动态规划
    for (int i = 0; i < n; i++) {
        for (int j = 0; j <= 10000; j++) {
            // 不选第i个菜
            dp[i + 1][j] = dp[i][j];
            // 选第i个菜
            if (j >= prices[i]) {
                dp[i + 1][j] |= dp[i][j - prices[i]];
            }
        }
    }
    
    // 从满足条件的最小价格开始找
    for (int total = x; total <= 10000; total++) {
        if (dp[n][total]) {
            cout << total << endl;
            break;
        }
    }
    
    return 0;
}

算法及复杂度

  • 算法:动态规划
  • 时间复杂度:,其中 是菜品数量, 是价格上限
  • 空间复杂度:,用于存储 数组