1. 程式人生 > 實用技巧 >火車站臺連鎖店(題解)

火車站臺連鎖店(題解)

火車站臺連鎖店 首先這道題是一道二分經典題(很難很難

我們為什麼要用二分呢,因為每一次選擇數字,無論偏大還是偏小,都可以讓剩下的選擇範圍縮小一半

我們先來看看題目及範圍

先來看看題目的意思:

大概的意思是我們要讓這n個站臺中的m個站臺裡,讓每兩個站臺間的距離都儘可能的大。

因為這道題要求輸出最大的最近距離,所以我們就來二分距離。

但是我們需要一個輔助函式bool來計算最短距離能開設多少家店。

bool ok(int x)
{
    int tot = 1;
    int last = 1;
    for(int i = 1; i <= n; i++)
    {
        
while(a[i]-a[last] < x) { i++; if(i > n) { return tot >= m; } } last = i; tot++; } return tot >= m; }

我們用tot和last這兩個臨時變數來儲存我們的資料(個人喜好)

怎麼實現查詢?
首先確定初始範圍
因為我們要把最短距離進行二分查詢,所以我們需要一個最初始的left以及right的值。可以肯定的是,這個最短距離L一定在1~最大座標-最小座標。

通過幾次查詢,如果我們不停下來的話,left,right,mid三個值都不會再發生變化

因為我們的二分寫發是

while(left<right)

因為我們二分的寫法是每次left和right其一等於mid,但當它們其中一個和mid相等的時候,這就會成為一個死迴圈

所以我們就需要改成

while(right - left > 1)

完整程式碼如下

#include <bits/stdc++.h>
using namespace std;
int n, m;
int a[100010];
bool ok(int x)
{
    int tot = 1;
    int
last = 1; for(int i = 1; i <= n; i++) { while(a[i]-a[last] < x) { i++; if(i > n) { return tot >= m; } } last = i; tot++; } return tot >= m; } int main() { cin >> n >> m; for(int i = 1; i <= n; i++) { cin >> a[i]; } sort(a+1,a+1+n); int l = 0, r = a[n]-a[1]; while(r-l>1) { int mid=(l+r)/2; if(ok(mid)) { l = mid; } else { r = mid; } } if(!ok(r)) { r = l; } cout << r; return 0; }

順便一說:

老大在天上一定也有籃球吧,今天是你的紀念日,一路走好。