GESP 2023年 六级 小杨买饮料 洛谷P3873题 解题思路和步骤 C++实现带注释 洛谷 leetcode
题目分析
该题属于动态规划中的01背包问题变种,要求选择若干种饮料(每种至多选一次),在总容量不低于L的前提下使花费最小。与标准01背包的区别在于:
1.容量要求是"不低于"而非"不超过"
2.需要处理无解情况
解题思路
1.状态定义:设dp[j]表示达到容量j时的最小花费
2.初始化:dp[0]=0(0容量花费为0),其他初始化为INF(表示不可达)
3.状态转移:对于每种饮料,逆序更新dp数组:dp[j] = min(dp[j], dp[max(j-w,0)] + c)
4.结果处理:在dp[L...maxL]范围内找最小值
实现步骤
1.输入饮料种类数N和需求容量L
2.初始化dp数组
3.处理每种饮料,更新dp值
4.检查是否有解并输出结果
代码实现
#include<iostream> #include<algorithm> using namespACe std; const int INF = 1e9; // 定义无穷大值 int main() { int N, L; cin >> N >> L; int cost[2001]; // dp数组 cost[0] = 0; // 初始状态 for(int i = 1; i <= 2000; i++) cost[i] = INF; // 初始化 // 处理每种饮料 for(int i = 0; i < N; i++) { int c, w; // 价格和容量 cin >> c >> w; // 逆序更新dp数组 for(int j = 2000; j >= 0; j--) { int new_j = min(j + w, 2000); // 防止数组越界 cost[new_j] = min(cost[new_j], cost[j] + c); } } // 在[L,2000]范围内找最小值 int ans = INF; for(int j = L; j <= 2000; j++) ans = min(ans, cost[j]); if(ans == INF) cout << "no solution"; else cout << ans; return 0; }
该解法时间复杂度O(N*maxL),其中maxL为最大可能容量2000。关键点在于逆向更新dp数组和结果范围的处理。
原创内容 转载请注明出处