P3550 [POI 2013] TAK-Taxis 題解
Kingsley1116 · · 题解
題目描述
Byteasar 想要從 Bytehole 鎮乘坐計程車前往 Bytepit 鎮,兩地之間的距離為
Byteasar 可以在任意地點換乘計程車,且所有計程車都從基地出發(無需返回基地)。任務是判斷 Byteasar 能否從 Bytehole 抵達 Bytepit,若可以,則求出所需的最少計程車數量;若不可,則輸出
輸入格式:
第一行包含三個整數
第二行包含
輸出格式:
輸出最少計程車數量,若無法抵達則輸出
思路
要完成旅程,需滿足兩個核心條件:
- 至少有一輛計程車能從基地抵達終點(即行駛距離
\ge 基地到終點的距離m-d )。 - 能通過換乘計程車,從起點(0 公里)抵達某個位置,使得最後一輛計程車能從基地出發,接載 Byteasar 並抵達終點。
具體步驟
-
特殊情況判斷:單輛計程車直達
若存在一輛計程車的行駛距離\ge d + m ,則它可從基地出發,先開到起點(距離d ),再直接開到終點(距離m ),此時只需 1 輛計程車。 -
篩選能抵達終點的計程車
基地到終點的距離為m-d ,因此需至少有一輛計程車的x_i \ge m-d (否則直接輸出 0)。
將計程車按行駛距離降序排序後,篩選出所有滿足x_i \ge m-d 的計程車,選取其中最強的一輛(即排序後的第一輛)作為「最後一輛」負責抵達終點。 -
貪心擴展覆蓋範圍
剩餘的計程車需用於覆蓋從起點到基地附近的距離。目標是通過換乘,讓 Byteasar 能抵達盡可能遠的位置(記為current),從而減少最後一輛計程車的負擔。- 每次選擇剩餘計程車中行駛距離最長的,計算其能擴展的覆蓋範圍:
current更新為2 \times current + (x_i - d) 。 - 若某次選擇的計程車無法擴展覆蓋範圍(
x_i \le d - current ),則無法抵達,輸出 0。
- 每次選擇剩餘計程車中行駛距離最長的,計算其能擴展的覆蓋範圍:
-
最終驗證
判斷最後一輛計程車能否覆蓋剩餘距離:需滿足m + d - 2 \times current \le x_{last} (其中x_{last} 是最後一輛計程車的行駛距離)。若滿足,則總計程車數量為「擴展用計程車數 + 1(最後一輛)」;否則輸出 0。
代碼實現
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
long long m, d, n;
cin >> m >> d >> n;
vector<long long> a(n);
for (long long i = 0; i < n; i++) cin >> a[i];
sort(a.rbegin(), a.rend());
if (a[0] >= m + d) {
cout << 1;
return 0;
}
long long pointer = 0;
for (; pointer < n; pointer++) {
if (a[pointer] < m - d) break;
}
pointer--;
if (pointer < 0) {
cout << 0;
return 0;
}
long long ans = 0, current = 0;
for (long long i = 0; i < n; i++) {
if (i == pointer) continue;
if (current >= d || m + d - 2 * current <= a[pointer]) break;
if (a[i] <= d - current) {
cout << 0;
return 0;
}
ans++;
current += a[i] - d + current;
if (current >= m) {
ans--;
break;
}
}
cout << ((m + d - 2 * current > a[pointer]) ? 0 : ans + 1);
return 0;
}