### 华为OD机试路灯问题编程解法
#### 问题分析
该问题是典型的区间覆盖问题,目标是计算在一段连续区域内未被覆盖的部分长度。具体来说,给定一系列路灯的位置及其对应的照明半径,需找出这些路灯未能完全照亮的区域总长度[^1]。
为了高效解决问题,可以采用如下方法:
1. **提取有效范围**:对于每一个路灯,基于其位置和照明半径,确定它能够照亮的具体区间。
2. **合并重叠区间**:通过排序并处理可能存在的区间交集,最终得到一组不相交的有效光照区间。
3. **计算空白部分**:利用已知的第一盏灯到最后一盏灯的整体距离减去实际被照亮的距离,得出剩余未被覆盖的长度。
以下是具体的算法设计以及不同语言下的代码实现示例。
---
#### Python 实现
```python
def unlit_length(road_lights, total_distance):
intervals = []
# 计算每个路灯的实际照射区间
for light in road_lights:
start = max(light['position'] - light['radius'], 0)
end = min(light['position'] + light['radius'], total_distance)
intervals.append((start, end))
# 对区间按照起点进行排序
intervals.sort(key=lambda x: x[0])
merged_intervals = []
prev_start, prev_end = None, None
# 合并不相交或者相邻的区间
for interval in intervals:
current_start, current_end = interval
if not merged_intervals or merged_intervals[-1][1] < current_start:
merged_intervals.append(interval)
prev_start, prev_end = current_start, current_end
else:
merged_intervals[-1] = (merged_intervals[-1][0], max(current_end, merged_intervals[-1][1]))
covered_length = sum(end - start for start, end in merged_intervals)
return total_distance - covered_length
# 测试数据
lights_data = [
{'position': 0, 'radius': 50},
{'position': 100, 'radius': 60}
]
total_road_length = 200
result = unlit_length(lights_data, total_road_length)
print(f"Uncovered length is {result} meters.")
```
上述程序定义了一个函数 `unlit_length` 来接收路灯列表与道路全长作为输入参数,并返回未被灯光覆盖路段的累计长度[^2]。
---
#### C++ 实现
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Light {
int position;
int radius;
};
int calculateUnlitLength(vector<Light> lights, int totalDistance) {
vector<pair<int, int>> intervals;
for(auto &light : lights){
int start = max(light.position - light.radius, 0);
int end = min(light.position + light.radius, totalDistance);
intervals.emplace_back(start, end);
}
sort(intervals.begin(), intervals.end());
vector<pair<int,int>> mergedIntervals;
for(auto &[s,e] : intervals){
if(!mergedIntervals.empty() && s <= mergedIntervals.back().second){
mergedIntervals.back().second = max(e, mergedIntervals.back().second);
}else{
mergedIntervals.emplace_back(s,e);
}
}
long long coveredSum = 0;
for(auto &[a,b] : mergedIntervals){
coveredSum += b-a;
}
return totalDistance - static_cast<int>(coveredSum);
}
// Example usage
int main(){
vector<Light> data{{0,50},{100,60}};
cout << "Uncovered Length:" << calculateUnlitLength(data,200)<<endl;
return 0;
}
```
此版本展示了如何用C++完成同样的逻辑操作。
---
#### Java 实现
```java
import java.util.*;
class Solution {
public static class Light {
int position;
int radius;
public Light(int p, int r) {
this.position = p;
this.radius = r;
}
}
public static int getUnlitLength(List<Light> lights, int totalDist) {
List<int[]> ranges = new ArrayList<>();
for(Light l : lights){
int begin = Math.max(l.position - l.radius, 0);
int finish = Math.min(l.position + l.radius, totalDist);
ranges.add(new int[]{begin,finish});
}
Collections.sort(ranges,(a,b)->Integer.compare(a[0],b[0]));
LinkedList<int[]> mergedRanges = new LinkedList<>();
for(var range : ranges){
if (!mergedRanges.isEmpty() && mergedRanges.getLast()[1]>=range[0]){
mergedRanges.setLast(new int[]{
mergedRanges.getLast()[0],
Math.max(range[1],mergedRanges.getLast()[1]) });
}else{
mergedRanges.addLast(range);
}
}
int coverdTotal=0;
for(var mrgRange : mergedRanges){
coverdTotal+=mrgRange[1]-mrgRange[0];
}
return totalDist-coverdTotal;
}
public static void main(String[] args) {
List<Light> list=new ArrayList<>(Arrays.asList(
new Light(0,50),
new Light(100,60)));
System.out.println(getUnlitLength(list,200));
}
}
```
这段Java代码同样实现了路灯间无光区段测量功能。
---
#### JavaScript 实现
```javascript
function findDarkSpots(lights, totalRoadLen){
let segments=[];
// 构建各灯泡影响范围数组
for(let i of lights){
const lowerBound=Math.max(i.pos-i.rad,0);
const upperBound=Math.min(i.pos+i.rad,totalRoadLen);
segments.push([lowerBound,upperBound]);
}
// 排序以便后续合并
segments.sort((a,b)=>a[0]-b[0]);
let combinedSegments=[segments.shift()];
while(segments.length!==0){
var nextSeg=segments.shift();
var lastCombined=combinedSegments.at(-1);
if(nextSeg[0]<=lastCombined[1]){
lastCombined[1]=Math.max(lastCombined[1],nextSeg[1]);
}else{
combinedSegments.push(nextSeg);
}
}
let litArea=combinedSegments.reduce((acc,[from,to])=>acc+(to-from),0);
return totalRoadLen-litArea;
}
const testLights=[
{"pos":0,"rad":50},{"pos":100,"rad":60}];
console.log(findDarkSpots(testLights,200)); // 输出应为40米
```
这是JavaScript版解决方案。
---
#### 总结
以上四种主流开发环境中的解答均遵循相同的核心理念——先求取单体光源作用域再综合评估整体遮蔽状况最后量化缺失比例。这种方法不仅适用于本题情境也广泛运用于其他涉及资源分配优化等领域的问题之中^。