路灯照明问题
真题目录: 点击去查看
E B卷 100分题型
题目描述
在一条笔直的公路上安装了N个路灯,从位置0开始安装,路灯之间间距固定为100米。
每个路灯都有自己的照明半径,请计算第一个路灯和最后一个路灯之间,无法照明的区间的长度和。
输入描述
第一行为一个数N,表示路灯个数,1<=N<=100000
第二行为N个空格分隔的数,表示路灯的照明半径,1<=照明半径<=100000*100
输出描述
第一个路灯和最后一个路灯之间,无法照明的区间的长度和.
用例1
输入
2
50 50
输出
none
0
说明
路灯1覆盖0-50,路灯2覆盖50-100,路灯1和路灯2之间(0米-100米)无未覆盖的区间。
用例2
输入
4
50 70 20 70
输出
none
20
说明
[170,180],[220,230],两个未覆盖的区间,总里程为20
题解
思路:
- 比较简单的一道题, 区间合并(注意可能出现递归合并)
c++
c++
#include<iostream>
#include<vector>
#include<string>
#include <utility>
#include <sstream>
#include<algorithm>
#include<stack>
using namespace std;
int main() {
int n ;
cin >> n;
vector<int> ans(n);
stack<pair<int,int>> stk;
for (int i = 0; i < n; i++) {
cin >> ans[i];
int left = (i * 100) - ans[i];
int right = (i*100) + ans[i];
// 递归区间合并
while (!stk.empty() && stk.top().second >= left) {
pair<int,int> tmp = stk.top();
stk.pop();
left = min(tmp.first, left);
right = max(tmp.second, right);
}
stk.push({left, right});
}
int res = 0;
// 计算多个区间中空白照明长度
while (stk.size() != 1) {
pair<int,int> top = stk.top();
stk.pop();
res += top.first - stk.top().second;
}
cout << res;
}
JAVA
JAVA
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] ranges = new int[n][2];
for (int i = 0; i < n; i++) {
int center = i * 100;
int r = sc.nextInt();
ranges[i][0] = center - r;
ranges[i][1] = center + r;
}
System.out.println(getResult(n, ranges));
}
public static int getResult(int n, int[][] ranges) {
int ans = 0;
// 按起始位置升序,起始位置相同,则继续按结束位置降序
Arrays.sort(ranges, (a, b) -> a[0] != b[0] ? a[0] - b[0] : b[1] - a[1]);
int t = ranges[0][1]; // 上一个区间的结束位置
for (int i = 1; i < n; i++) {
// 当前区间的【开始位置,结束位置】
int s = ranges[i][0];
int e = ranges[i][1];
// 有交集
if (t >= s) {
// 合并后的新区间将变为下一轮的上一个区间,t为新区间的结束位置
t = Math.max(e, t);
} else {
// 没有交集,则统计区间间隙 s - t
ans += s - t;
// 当前区间变为下一轮的上一个区间,更新t
t = e;
}
}
return ans;
}
}
Python
python
# 输入获取
n = int(input())
arr = list(map(int, input().split()))
# 算法入口
def getResult():
rans = []
for i in range(n):
center = i * 100
rans.append([center - arr[i], center + arr[i]])
# 按起始位置升序,起始位置相同,则继续按结束位置降序
rans.sort(key=lambda ran: (ran[0], -ran[1]))
ans = 0
t = rans[0][1] # 上一个区间的结束位置
for i in range(1, n):
s, e = rans[i] # 当前区间的【开始位置,结束位置】
# 有交集
if t >= s:
# 合并后的新区间将变为下一轮的上一个区间,t为新区间的结束位置
t = max(e, t)
else:
# 没有交集,则统计区间间隙 s - t
ans += s - t
# 当前区间变为下一轮的上一个区间,更新t
t = e
return ans
# 算法调用
print(getResult())
JavaScript
js
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const lines = [];
rl.on("line", (line) => {
lines.push(line);
if (lines.length === 2) {
const n = lines[0] - 0;
// 处理输入
const arr = lines[1].split(" ").map(Number);
console.log(getResult(n, arr));
lines.length = 0;
}
});
function getResult(n, arr) {
const ranges = [];
for (let i = 0; i < n; i++) {
const center = i * 100;
ranges.push([center - arr[i], center + arr[i]]);
}
// 按起始位置升序,起始位置相同,则继续按结束位置降序
ranges.sort((a, b) => (a[0] != b[0] ? a[0] - b[0] : b[1] - a[1]));
let ans = 0;
let t = ranges[0][1]; // 上一个区间的结束位置
for (let i = 1; i < n; i++) {
const [s, e] = ranges[i]; // 当前区间的【开始位置,结束位置】
// 有交集
if (t >= s) {
// 合并后的新区间将变为下一轮的上一个区间,t为新区间的结束位置
t = Math.max(e, t);
} else {
// 没有交集,则统计区间间隙 s - t
ans += s - t;
// 当前区间变为下一轮的上一个区间,更新t
t = e;
}
}
return ans;
}
Go
go
package main
import (
"fmt"
)
func main() {
var n int
fmt.Scan(&n)
ans := make([]int, n)
for i := 0; i < n; i++ {
fmt.Scan(&ans[i])
}
type Interval struct {
left int
right int
}
stack := []Interval{}
for i := 0; i < n; i++ {
left := i*100 - ans[i]
right := i*100 + ans[i]
// 合并重叠区间
for len(stack) > 0 && stack[len(stack)-1].right >= left {
top := stack[len(stack)-1]
stack = stack[:len(stack)-1]
left = min(top.left, left)
right = max(top.right, right)
}
stack = append(stack, Interval{left, right})
}
// 计算区间之间的空白长度
res := 0
for i := 1; i < len(stack); i++ {
res += stack[i].left - stack[i-1].right
}
fmt.Println(res)
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}