PTA 3 回溯法解0-1揹包問題
阿新 • • 發佈:2020-12-14
(圖片即連結)
只需要對於每一個學生,找到使其股份與錄取線的差最小的學校即可,所有差值之和即為答案.
通過把學校錄取線排序後二分查詢可以提高效率,這裡的資料線性查詢會爆.
將陣列升序排列,使用upper_bound查詢錄取線不低於學生分數的第一個學校,則上一個學校低於學生分數,顯然在這兩者之間選擇才會有最小差值,取min即可.
注意到當多個學校錄取線相同時,這個演算法也不會受到影響.
真正的關注點是邊界情況:學生的分數低於所有錄取線,和學生的分數高於所有錄取線.
前者情況下upper_bound返回陣列位置0,後者返回陣列末尾之後第一個位置(即a[m],而陣列末尾是a[m-1]).
這時處理起來仍然很簡單.
#include <algorithm> #include <cmath> #include <cstdio> #include <cstring> #include <iostream> using namespace std; int n, m, a[100010], b[100010]; long long ans; int main() { cin >> m >> n; for (int i = 0; i < m; i++) cin >> a[i]; // school m for(int i = 0; i < n; i++) cin >> b[i]; // student n sort(a, a + m); // m = unique(a, a + m) - a; // 後來才發現這裡不需要去重 for (int i = 0; i < n; i++) { int sad; int l = upper_bound(a, a + m, b[i]) - a - 1; int r = l + 1; if (l == m) // 特判 sad = b[i] - a[m - 1]; else if (l == -1) // 特判 sad = a[0] - b[i]; else sad = min(abs(b[i] - a[l]), abs(b[i] - a[r])); // 一般情況 ans += sad; } cout << ans << endl; return 0; }