1. 程式人生 > 其它 >PTA 3 回溯法解0-1揹包問題

PTA 3 回溯法解0-1揹包問題

(圖片即連結)

只需要對於每一個學生,找到使其股份與錄取線的差最小的學校即可,所有差值之和即為答案.

通過把學校錄取線排序後二分查詢可以提高效率,這裡的資料線性查詢會爆.

將陣列升序排列,使用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; }