题目
解题思路
使用动态规划求解:
- 状态定义: d p [ i ] [ j ] dp[i][j] dp[i][j] 表示前 i i i 个菜品中,是否能凑出总价 j j j
- 状态转移:
- 不选第 i i i 个菜: d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j] = dp[i-1][j] dp[i][j]=dp[i−1][j]
- 选第 i i i 个菜: d p [ i ] [ j ] = d p [ i − 1 ] [ j − p r i c e s [ i ] ] dp[i][j] = dp[i-1][j-prices[i]] dp[i][j]=dp[i−1][j−prices[i]]
- 从满足条件的最小价格开始向上找第一个可以凑出的价格
代码
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;
}
算法及复杂度
- 算法:动态规划
- 时间复杂度: O ( n ⋅ M ) \mathcal{O}(n \cdot M) O(n⋅M),其中 n n n 是菜品数量, M M M 是价格上限
- 空间复杂度: O ( n ⋅ M ) \mathcal{O}(n \cdot M) O(n⋅M),用于存储 d p dp dp数组
1369

被折叠的 条评论
为什么被折叠?



