松雅旅馆(实验三第二题)

题目在这里插入图片描述# 代码区

#include <iostream>
//松雅旅店 
#include <cmath>
using namespace std;
int main(){
	int n=0,m=0,a=0,d=0,door=0; 

	cin>>n>>m>>a>>d;
		int arr[m];
	for(int i=0;i<m;i++){
		cin>>arr[i];         //输入客人进入的时间 
	}
	int time_max=0 ;
	time_max=max(arr[m-1],n*a);     //找出最大时间点 
	int line [time_max];
	for(int i =0;i<time_max;i++){
		line[i]=0;                 //把总时间线中的元素全搞为 0
	}
	for(int i =0;i<m;i++){
		line[arr[i]-1]=1;
	}                        //把有客人进入的时间线搞为1 
	for(int i=0;i<n;i++){
		line [(i+1)*a-1] =1;
	}
	for(int i =0;i<time_max;i++){
		if (line[i]==1){
			door++;
			i=i+d;          //根据数组赋值是否为1来判断是否有人 
		}
	}
	cout<<door;
	return 0;
}
# 目重述 在一条无限长的直线上,每个整数坐标代表一座城市。已有 $ n $ 家旅馆,分别位于互不相同的坐标 $ x_1, x_2, \dots, x_n $(按严格递增给出)。她希望新建一家旅馆,使得这家新旅馆到**所有已有旅馆的最短距离恰好等于 $ d $**。 即:设新旅馆建在位置 $ p $,则必须满足: $$ \min_{i=1}^n |p - x_i| = d $$ 求满足条件的整数坐标 $ p $ 的个数。 --- # 详解 我们要找所有整数位置 $ p $,使得它到已有旅馆集合的最小距离 **正好是 $ d $**。 定义函数: $$ f(p) = \min_{i=1}^n |p - x_i| $$ 目标是求满足 $ f(p) = d $ 的整数点 $ p $ 的数量。 ## 关键观察: - 若 $ f(p) = d $,说明: 1. 存在至少一个已有旅馆 $ x_i $,使得 $ |p - x_i| = d $ 2. 对所有 $ x_j $,都有 $ |p - x_j| \geq d $,且至少有一个取等号(即最小值为 $ d $) 换句话说,$ p $ 必须**恰好距离某个已有旅馆为 $ d $**,并且不能比 $ d $ 更接近任何其他旅馆。 ### 候选位置来源: 对于每个现有旅馆 $ x_i $,考虑两个可能的位置: - $ p = x_i + d $ - $ p = x_i - d $ 这些是唯一可能满足“与 $ x_i $ 距离为 $ d $”的位置。 我们枚举这 $ 2n $ 个候选点,然后对每个点判断是否满足: $$ \min_j |p - x_j| = d $$ 注意:不能直接统计所有这样的点,因为可能会重复(比如多个 $ x_i $ 生成同一个 $ p $),也不能保证该点真的最小距离就是 $ d $ —— 可能它离另一个更近的旅馆小于 $ d $! ### 正确做法步骤: 1. 将已有旅馆坐标存入数组 $ X $,并排序(目已保证有序)。 2. 使用一个集合(如 `set`)记录所有合法且唯一的 $ p $。 3. 对每个 $ x_i $: - 尝试 $ p = x_i + d $ - 尝试 $ p = x_i - d $ - 对每个候选 $ p $,计算其到最近已有旅馆的距离 $ \min_j |p - x_j| $ - 如果这个最小距离 **等于 $ d $**,则计入答案 4. 注意去重,同一个 $ p $ 可能由多个 $ x_i $ 生成 但如何快速计算 $ \min_j |p - x_j| $? 由于 $ X $ 有序,可以用二分查找找到最接近 $ p $ 的旅馆。 具体方法: - 用 `lower_bound` 找第一个 $ \geq p $ 的位置 - 比较其与前一个元素的距离,取最小值 ### 实现优化: 使用 `std::lower_bound` 找插入位置,然后比较左右邻居。 --- ### 示例验证: 输入: ``` n=3, d=3 x = [1, 5, 8] ``` 候选点: - 来自 $ x=1 $: $ 1+3=4 $, $ 1-3=-2 $ - 来自 $ x=5 $: $ 5+3=8 $, $ 5-3=2 $ - 来自 $ x=8 $: $ 8+3=11 $, $ 8-3=5 $ 检查每个点: 1. $ p=4 $: 到 $[1,5,8]$ 的距离为 $ |4-1|=3, |4-5|=1, |4-8|=4 $ → 最小是 1 ≠ 3 → 排除 2. $ p=-2 $: 到各点距离:3,7,10 → min=3 → ✅ 3. $ p=8 $: 已有旅馆在此 → 距离为 0 → ❌ 4. $ p=2 $: 到 1→1, 5→3, 8→6 → min=1 → ❌ 5. $ p=11 $: 到 8→3, 5→6, 1→10 → min=3 → ✅ 6. $ p=5 $: 已存在旅馆 → 距离为 0 → ❌ 有效点:-2 和 11 → 输出 2 --- # 知识点 - **二分查找在有序数组中的应用**:使用 `lower_bound` 快速定位最接近某点的元素,用于计算最小距离。 - **去重枚举法求解构造问**:通过分析解的必要条件(必须距离某个原点为 $ d $),生成有限候选集并验证。 - **最小距离约束的精确满足**:要求 $\min |p - x_i| = d$,需同时满足“存在等于 $ d $”和“不存在小于 $ d $”两个条件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值