日常訓練 20170612 星之船

題目描述:
  站臺的長度是 L ,星之船最左側的門稱爲第 1 個門,對於滿足 1iN 的整數,星之船的第 i 個門與第 1 個門之間的距離是 Di ,並且有 0=D1<D2<<DN1<DNL 。站臺上有 M 個乘客,對於滿足 1iM 的整數,第 i 個乘客距離站臺左邊緣的距離爲 Pi ,那麼有 0P1P2PML 。如果星之船停在 S 這個位置,也就是說星之船的第 1 個門正對着站臺的位置距離站臺左邊緣的距離是 S ,那麼由於所有的門都要正對站臺,顯然有 0SLDN 。此時,星之船的第 i 個門正對站臺的位置就是 S+Di
  如果第 i 個乘客從第 j 個門上車,由於星之船的體積巨大,門的大小可以忽略不計,那麼他需要的時間就是 |Dj+SPi| 。當然,所有的乘客都會選擇需要時間最小的門上車。lqr目測了下一個停靠站臺的情況,請你幫助她計算使得所有乘客上車時間最長的停靠位置 S ,以及此時所有乘客上車所需的時間總和。
數據範圍:
  0<L109,M300,N3000<L109,M300,N300
題解:
  L 很長,所以不能枚舉每一個點,考慮有哪些必要枚舉的點。可以證明只要枚舉每個乘客在兩個站點中點和車在最左和最右的位置就能找到解。考慮一個最優解車不在最左和最右位置並且沒有乘客在兩站點中點,那麼每個乘客都有一個確定上車的門,我們對於每一個乘客找到使他能夠多走一點的方向(就是他上的門的反向),對於兩個方向,必然有一個方向能使乘客走的總路程至少不減,直到移到邊緣或有人移到兩站中點。

#include<bits/stdc++.h>
typedef long long ll;
const int N = 305;
int n, m, cnt;
ll L, P[N], D[N], S[N * N * 2];
void add(int x) {if (x >= 0 && x <= L - D[n]) S[++cnt] = x;}
int main() {
    scanf("%lld%d", &L, &m); L <<= 1;
    for (int i = 1; i <= m; i++)
        scanf("%lld", &P[i]), P[i] <<= 1;
    scanf("%d", &n);
    for (int i = 2; i <= n; i++)
        scanf("%lld", &D[i]), D[i] <<= 1;
    for (int i = 1; i <= m; i++)
        for (int j = 1; j < n; j++)
            add(P[i] - (D[j] + D[j + 1]) / 2);
    add(0); add(L - D[n]);
    std::sort(S + 1, S + cnt + 1);
    ll ans = 0, det;
    for (int k = 1; k <= cnt; k++) {
        int p = 1;
        ll tans = 0;
        for (int i = 1; i <= m; i++) {
            while (p < n && abs(D[p + 1] + S[k] - P[i]) < abs(D[p] + S[k] - P[i])) p++;
            tans += abs(D[p] + S[k] - P[i]);
        }
        if (tans > ans)
            ans = tans,
            det = S[k];
    }
    printf("%.1f %.1f\n", det * 0.5, ans * 0.5);
    return 0;
}

如有侵權,請聯繫作者刪除。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章