最大訪客數

December 1, 2021

現將舉行一個餐會,訪客事先會填寫到達時間與離開時間,為了掌握座位數量,必須先估計不同時間的最大訪客數。

解法思路

單就計算訪客數這個目的,同時考慮同一訪客的來訪時間與離開時間,會使程式變得複雜;只要將來訪時間與離開時間分開處理就可以了,假設訪客 i 的來訪時間為 x[i],而離開時間為 y[i]

在資料輸入完畢之後,將 x[i]y[i] 分別進行排序(由小到大),先計算某時之前總共來訪了多少訪客,然後再減去某時之前的離開訪客,就可以輕易地解出這個問題。

程式實作

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

#define GUESTS 30

int compare(const void*, const void*);
int max(int[][GUESTS], int, int); 

int main(void) { 
    srand(time(NULL)); 
    
    int visits[2][GUESTS] = {0};
    
    int i;
    for(i = 0; i < GUESTS; i++) {
        visits[0][i] = (double) rand() / RAND_MAX * 24;
        visits[1][i] = (double) rand() / RAND_MAX * 
            (24 - visits[0][i]) + visits[0][i];
    }

    // 預先排序 
    qsort(visits[0], GUESTS, sizeof(int), compare);
    qsort(visits[1], GUESTS, sizeof(int), compare);

    int t;
    for(t = 0; t < 24; t++) {
        int num = max(visits, GUESTS, t);
        if(num != 0) {
            printf("%2d 時訪客數:%2d 位\n", t, num); 
        }             
    }
    
    return 0; 
} 

int compare(const void* a, const void* b) {
    return *(int*)a - *(int*)b;
}

int max(int visits[][GUESTS], int count, int time) { 
    int num, i;
    for(num = 0, i = 0; i <= count; i++) {
        num = time > visits[0][i] ? num + 1 : num;
        num = time > visits[1][i] ? num - 1 : num;
    } 
    return num; 
}  
import java.util.*;
import static java.lang.System.out;
import static java.util.Arrays.*;
import static java.lang.Math.random;

class Visitor {
    final int start;
    final int end;
    public Visitor(int start, int end) {
        this.start = start;
        this.end = end;
    }
}

public class Visitors {
    private List<Visitor> visitors = new ArrayList<>();
    
    public void add(Visitor v) {
        visitors.add(v);
    }
    
    public int max(int time) {
        return max(time, sortedSE());
    }
    
    public int[] max() {
        int[][] se = sortedSE();
        int[] timeList = new int[24];
        for(int t = 0; t < 24; t++) { 
            timeList[t] = max(t, se);
        } 
        return timeList;
    }
    
    private int[][] sortedSE() {
        int[][] se = new int[2][visitors.size()];
        for(int i = 0; i < visitors.size(); i++) {
            se[0][i] = visitors.get(i).start;
            se[1][i] = visitors.get(i).end;
        }
        sort(se[0]);
        sort(se[1]);
        return se;
    }
    
    private int max(int time, int[][] se) {
        int num = 0; 
        for(int i = 0; i < se[0].length; i++) { 
            num = time > se[0][i] ? num + 1 : num;
            num = time > se[1][i] ? num - 1 : num;
        } 
        return num;        
    }
    
    public static void main(String[] args) {
        final int GUESTS = 30;
        Visitors visitors = new Visitors();
        for(int i = 0; i < GUESTS; i++) {
            int start = (int) (random() * 24);
            int end = (int) (start + random() * (24 - start));
            visitors.add(new Visitor(start, end));
        }
    
        int[] guests = visitors.max();
        for(int t = 0; t < 24; t++) { 
            out.printf("%2d 時訪客:%2d 位%n", t, guests[t]); 
        } 
    }
} 
from functools import reduce
from random import random

def max(visits, time):
    return reduce(lambda num, t: num - 1 if time > t else num, visits[1],
        reduce(lambda num, t: num + 1 if time > t else num, visits[0] , 0))
        
GUESTS = 30
starts = [int(random() * 24) for i in range(GUESTS)]
ends = [int(random() * (24 - start) + start) for start in starts]

visits = [sorted(starts), sorted(ends)]
for t in range(24):
    num = max(visits, t)
    if num != 0:
        print("%2d 時訪客:%2d 位" % (t, num))
import java.lang.Math._

def max(visits: List[List[Int]], time: Int) = {
    ((0 /: visits(0)) {(num, t) => if(time > t) num + 1 else num} 
        /: visits(1)) {(num, t) => if(time > t) num - 1 else num}
}

val GUESTS = 30
val starts = for(i <- 0 until GUESTS) yield (random * 24).toInt
val ends = for(start <- starts) yield 
               (random * (24 - start) + start).toInt

val visits = List(starts.sortWith(_ > _).toList, ends.sortWith(_ > _).toList)
for(
    t <- 0 until 24;
    num = max(visits, t)
    if num != 0
) { printf("%2d 時訪客:%2d 位%n", t, num) }
# encoding: UTF-8
def max(visits, time)
    visits[1].reduce(
        visits[0].reduce(0) {|num, t| time > t ? num + 1 : num }
    ) {|num, t| time > t ? num - 1 : num}
end
        
GUESTS = 30
starts = (0...GUESTS).map {(rand * 24).to_i}
ends = starts.map {|start| (rand * (24 - start) + start).to_i}

visits = [starts.sort, ends.sort]
(0...24).each do |t|
    num = max(visits, t)
    if num != 0
        printf("%2d 時訪客:%2d 位\n", t, num)
    end
end
function max(visits, time) {
    var num = 0;
    for(var t = 0; t < visits[0].length; t++) {
        num = time > visits[0][t] ? num + 1 : num;
        num = time > visits[1][t] ? num - 1 : num;
    }
    return num;
}

var GUESTS = 30;
var visits = [[], []];
for(var i = 0; i < GUESTS; i++) {
    visits[0][i] = parseInt(Math.random() * 24);
    visits[1][i] = parseInt(Math.random() * 
                     (24 - visits[0][i]) + visits[0][i]);
}
var result = '';
for(var t = 0; t < 24; t++) {
    num = max(visits, t);
    if(num != 0) { result += (t + '時訪客:' + num + '位\n'); }
}
print(result);
import System.Random
import Control.Monad
import Text.Printf

rand gen n= take n \$ randomRs (0.0, 1.0) gen::[Float]

maxV visits time = foldl (count (-))
    (foldl (count (+)) 0 (visits !! 0)) (visits !! 1)
    where count op num t = if time > t then num `op` 1 else num

main = do
    gen1 <- getStdGen
    gen2 <- newStdGen
    let guests = 30
        starts = map (truncate . (* 24)) (rand gen1 guests)
        rs = (rand gen1 guests)
        ends = [truncate ((rs !! i) * fromIntegral(
            24 - (starts !! i))) + (starts !! i)| i <- [0..guests - 1]]
        visits = [starts, ends]
    print visits
    forM [0..23] (\t -> do
        let num = maxV visits t
        printf "%2d has %2d guests\n" (t::Int) (num::Int))