华为非AI方向笔试真题 6月24号【电影放映调度问题】

电影放映调度问题(C++/Py/Java/Js/Go)题解

华为笔试真题 6月24号 非AI方向第一题 100分题型

题目内容

某电影院有 111 块银幕,每天需要安排多部电影在不同时段进行放映。每部电影有固定的放映时长和要求的放映时间段,且每个被选中放映的电影确保在对应时段能够完整占用。由于每块银幕同一时间只能放映一部电影,需要合理规划,使得每天能够放映的电影数量最多。如果第一场电影结束时间与第二场电影的开始时间相同,能够连续放映。

给定 nnn 部电影的放映时间区间,请计算最多可以放映多少部电影。

输入描述

第一行: nnn (电影数量) , 1≤n≤1051 \le n \le 10^51≤n≤105

接下来 nnn 行: 每行两个整数 startistartistarti 和 endiendiendi , 表示第 iii 部电影的放映开始时间和结束时间, 0≤starti<endi≤14400 \le starti < endi \le 14400≤starti<endi≤1440 (一天内的分钟数) (时间以分钟表示, 111 小时为 606060 分钟; 如 9:00=5409:00 = 5409:00=540, 12:00=72012:00 = 72012:00=720)

输出描述

一个整数: 最多可以放映的电影数量

样例1

输入

复制代码
3
540 660
540 600
660 780

输出

复制代码
2

说明

最多可以 222 部电影, 可以选择 540540540-660660660 和 660660660-780780780, 或者 540540540-600600600 和 660660660-780780780

样例2

输入

复制代码
5
0 1000
100 900
200 800
300 700
400 600

输出

复制代码
1

说明

因为各电影的播放时间均有重叠, 所以最多可以有一部电影播放

题解和思路

思路

实现思路:贪心

  1. 这类求不重叠区间是一种常见贪心题型。贪心基于尽可能选择结束时间早的区间,将更多时间留给后续活动,从而达到选择尽可能多的区间数量。
  2. 先对时间区间按照结束时间升序排序。
  3. 从前往后遇到不冲突的区间进行选择即可,然后记录选择区间数量。
  4. 算法总体时间复杂度为O(nlogn)

C++

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<pair<int,int>> range(n);
    for (int i = 0; i < n; i++) {
        int start,end;
        cin >> start >> end;
        range[i] = {start, end};
    }
    // 按终止时间升序
    sort(range.begin(), range.end(), [](pair<int, int>& p1, pair<int, int>& p2){
       return  p1.second < p2.second;
    });
    
    // 贪心能选择就选择
    int cnt = 0;
    int lastEnd = -1;
    for (int i = 0; i < n; i++) {
        if (range[i].first >= lastEnd) {
            cnt++;
            lastEnd = range[i].second;
        }
    }
    cout << cnt;
    return 0;
}

Java

java 复制代码
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int n = Integer.parseInt(br.readLine());

        int[][] range = new int[n][2];

        for (int i = 0; i < n; i++) {
            String[] strs = br.readLine().split(" ");
            range[i][0] = Integer.parseInt(strs[0]);
            range[i][1] = Integer.parseInt(strs[1]);
        }

        // 按终止时间升序
        Arrays.sort(range, (a, b) -> Integer.compare(a[1], b[1]));

        // 贪心能选择就选择
        int cnt = 0;
        int lastEnd = -1;

        for (int i = 0; i < n; i++) {
            if (range[i][0] >= lastEnd) {
                cnt++;
                lastEnd = range[i][1];
            }
        }

        System.out.print(cnt);
    }
}

python

python 复制代码
import sys

n = int(sys.stdin.readline())

range_list = []

for _ in range(n):
    start, end = map(int, sys.stdin.readline().split())
    range_list.append([start, end])

# 按终止时间升序
range_list.sort(key=lambda x: x[1])

# 贪心能选择就选择
cnt = 0
last_end = -1

for start, end in range_list:
    if start >= last_end:
        cnt += 1
        last_end = end

print(cnt)

Javascript

js 复制代码
const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

const input = [];

rl.on('line', line => {
    input.push(line);
});

rl.on('close', () => {
    let idx = 0;

    const n = Number(input[idx++]);

    const range = [];

    for (let i = 0; i < n; i++) {
        const [start, end] = input[idx++].split(" ").map(Number);
        range.push([start, end]);
    }

    // 按终止时间升序
    range.sort((a, b) => a[1] - b[1]);

    // 贪心能选择就选择
    let cnt = 0;
    let lastEnd = -1;

    for (let i = 0; i < n; i++) {
        if (range[i][0] >= lastEnd) {
            cnt++;
            lastEnd = range[i][1];
        }
    }

    console.log(cnt);
});

Go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
)

type Pair struct {
	start int
	end   int
}

func main() {
	in := bufio.NewReader(os.Stdin)

	var n int
	fmt.Fscan(in, &n)

	ranges := make([]Pair, n)

	for i := 0; i < n; i++ {
		fmt.Fscan(in, &ranges[i].start, &ranges[i].end)
	}

	// 按终止时间升序
	sort.Slice(ranges, func(i, j int) bool {
		return ranges[i].end < ranges[j].end
	})

	// 贪心能选择就选择
	cnt := 0
	lastEnd := -1

	for i := 0; i < n; i++ {
		if ranges[i].start >= lastEnd {
			cnt++
			lastEnd = ranges[i].end
		}
	}

	fmt.Print(cnt)
}