[白俊2513]スクールバス



  • 質問:2513番バス

  • タイプ:グリディ

  • 考え方:問題は1461号問題と同じ方法で解決すればよい.学校を基準に、座標が負数の区間と譲受区間を分けて計算し、負数区間は絶対値が最大の点から、最大限バスに積み込み、移動距離を算出し、譲受区間も同様に計算すればよい.

  • まず学校の座標からの全距離を求め、負の区間と正の区間に分けます.負数区間では最小の臀部を用い,最大k人を繰り返し搬送し,距離を計算し,揚水区間では最大の臀部に座標を加え,同様に最大k人まで搬送し,距離を計算した.

  • コード#コード#
  • #include <bits/stdc++.h>	
    
    const int dx[4] = { 1,0,-1,0 };
    const int dy[4] = { 0,-1,0,1 };
    
    using namespace std;
    	
    int n, k, s;
    pair<int, int > p[30001];
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
    
    int main() {
    	cin.tie(0); cout.tie(0); ios_base::sync_with_stdio(false);
    	cin >> n >> k >> s;
    	for (int i = 0; i < n; i++) {
    		cin >> p[i].first >> p[i].second;
    	}
    	p[n] = { s,0 };
    	sort(p, p + n + 1);
    	int T = lower_bound(p, p + n + 1, make_pair(s, 0)) - p;
    	for (int i = 0; i < T; i++) pq.push({ p[i].first - s, p[i].second });
    
    	int ans = 0;
    	int t = k;
    	int c = 0;
    	while (!pq.empty()) {
    		if(t == k)
    			c += abs(pq.top().first);
    		if (pq.top().second <= t) {
    			t -= pq.top().second;
    			pq.pop();
    			if (t == 0) {
    				ans += 2 * c;
    				t = k;
    				c = 0;
    			}
    		}
    		else {
    			auto temp = pq.top();
    			temp.second -= t;
    			t = k;
    			pq.pop();
    			pq.push(temp);
    		}
    	}
    	ans += 2 * c;
    
    	priority_queue<pair<int, int>> Q;
    	for (int i = T + 1; i <= n; i++) Q.push({ p[i].first - s, p[i].second });
    	t = k;
    	c = 0;
    	while (!Q.empty()) {
    		if (t == k)
    			c += abs(Q.top().first);
    		if (Q.top().second <= t) {
    			t -= Q.top().second;
    			Q.pop();
    			if (t == 0) {
    				ans += 2 * c;
    				t = k;
    				c = 0;
    			}
    		}
    		else {
    			auto temp = Q.top();
    			temp.second -= t;
    			t = k;
    			Q.pop();
    			Q.push(temp);
    		}
    	}
    	ans += 2 * c;
    
    	cout << ans;
    	return 0;
    }