該題運用貪心算法,核心思想是在每次分組時,盡可能讓價格較小和較大的紀念品組合在一起,以達到最少分組的目的。
【算法思路】
-
輸入處理:首先讀取紀念品的數量n和價格上限w,然后依次讀取每件紀念品的價格,并將其存儲在容器vector中
-
排序:使用 sort 函數對紀念品的價格進行從小到大的排序。排序的目的是方便后續使用雙指針法,能快速找到價格最小和最大的紀念品。
-
雙指針初始化:初始化兩個指針 left 和 right,分別指向價格最小和最大的紀念品。同時,初始化分組數量 groups 為 0。
-
分組過程:
? 當 left 小于等于 right 時,進入循環:
? 如果 left 等于 right,說明只剩下一個紀念品,將分組數量加 1 并跳出循環。
? 如果價格最小和最大的紀念品價格之和不超過價格上限 w ,則將它們分為一組,left 指針右移一位,right 指針左移一位,分組數量加 1。
? 如果價格最小和最大的紀念品價格之和超過價格上限 w ,則將價格最大的紀念品單獨分為一組,right 指針左移一位,分組數量加 1。 -
輸出結果:循環結束后,輸出分組的數量。
【代碼示例】
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int main() {int w, n;// 讀取每組紀念品價格上限 w 和紀念品數量 ncin >> w;cin >> n;// 使用 n 來初始化 vector 的大小vector<int> P(n);// 讀取每個紀念品的價格for (int i = 0; i < n; i++) {cin >> P[i];}// 對紀念品價格從小到大排序sort(P.begin(), P.end());// 雙指針法分組int left = 0;int right = n - 1;// 初始化分組數量為 0int groupCount = 0;while (left <= right) {if (left == right) {// 若只剩一個紀念品,單獨成一組groupCount += 1;break;}if (P[left] + P[right] <= w) {// 若最小和最大價格的紀念品能分在一組groupCount += 1;left += 1;right -= 1;} else {// 若不能,最大價格的紀念品單獨成一組right -= 1;groupCount += 1;}}// 輸出最少的分組數量cout << groupCount << endl;return 0;
}
注意:
①雙指針一般是整數類型的索引,而非指針類型
②使用 n 來初始化 vector 的大小
③將groupCount初始化為0,避免未定義行為