洛谷P1618烦恼的高考志愿

本文介绍了一个帮助学生寻找最佳大学志愿填报方案的算法。通过将学校分数线排序并使用二分查找法,为每位学生找到预估分与分数线差异最小的学校,从而实现不满意度之和最小化。

题目背景

计算机竞赛小组的神牛V神终于结束了高考,然而作为班长的他还不能闲下来,班主任老t给了他一个艰巨的任务:帮同学找出最合理的大学填报方案。可是v神太忙了,身后还有一群小姑娘等着和他约会,于是他想到了同为计算机竞赛小组的你,请你帮他完成这个艰巨的任务。

题目描述

现有m(m≤100000) 所学校,每所学校预计分数线是 ai​(ai​≤106)。有 n(n≤100000) 位学生,估分分别为bi​(bi​≤106)。

根据n位学生的估分情况,分别给每位学生推荐一所学校,要求学校的预计分数线和学生的估分相差最小(可高可低,毕竟是估分嘛),这个最小值为不满意度。求所有学生不满意度和的最小值。

输入格式

第一行读入两个整数m,n。m表示学校数,n表示学生数。第二行共有m个数,表示m个学校的预计录取分数。第三行有n个数,表示n个学生的估分成绩。

输出格式

一行,为最小的不满度之和。

输入输出样例

输入 #1复制

4 3
513 598 567 689
500 600 550

输出 #1复制

32

解题思路:

先将学校的预计录取分数线排好序,然后用二分查找查找每一个学生的估分成绩在这里面的大概位置。再将这个位置以及前后位置的各个数依次与这个数相减,选出绝对值最小的那个,进行累加。需要注意的是如果返回的位置是1,我们要返回后一个位置,避免跟a[0]相减。

代码如下:

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int a[100001], b[100001],m,n;
int find(int x)
{
	int low = 1, high, mid;
	high = m;
	while (low <= high)
	{
		mid = (low + high) / 2;
		if (a[mid] == x) return mid;
		else if (a[mid] < x) low = mid + 1;
		else high = mid - 1;
	}
	if (mid == 1) return mid + 1;
	else return mid;
}
int main()
{
	int i,minx,y,sum=0;
	cin >> m>>n;
	for (i = 1; i <= m; i++) cin >> a[i];
	for (i = 1; i <= n; i++) cin >> b[i];
	sort(a + 1, a + m + 1);
	for (i = 1; i <= n; i++)
	{
		minx = 0x7fffffff;
		y=find(b[i]);
		minx = min(minx, abs(a[y] - b[i]));
		minx = min(minx, abs(a[y - 1] - b[i]));
		minx = min(minx, abs(a[y + 1] - b[i]));
		sum += minx;
	}
	cout << sum << endl;
	return 0;
}

zbh

### Python 实现高考志愿问题解决方案 此问题是关于如何通过编程来解决学生估分学校预计分数线之间的匹配问题。目标是最小化所有学生满意度。 以下是基于二分查找方法实现的一个完整的 Python 解决方案: #### 代码实现 ```python def solve_gaokao_problem(): import sys input_data = sys.stdin.read() lines = input_data.splitlines() # 获取输入数据中的 n m 值 n, m = map(int, lines[0].split()) # 学生估分列表 student_scores = list(map(int, lines[1].split())) # 学校预计分数线列表 school_lines = list(map(int, lines[2].split())) # 对学生成绩进行排序以便后续操作优化效率 student_scores.sort() total_dissatisfaction = 0 def binary_search(target): """ 使用二分查找找到最接近 target 的学校分数 """ low, high = 0, len(student_scores) - 1 closest_diff = float('inf') # 初始化最大差异 while low <= high: mid = (low + high) // 2 current_difference = abs(student_scores[mid] - target) if current_difference < closest_diff: closest_diff = current_difference if student_scores[mid] < target: low = mid + 1 elif student_scores[mid] > target: high = mid - 1 else: break # 完全相等的情况提前退出 return closest_diff for line in school_lines: dissatisfaction_for_line = binary_search(line) total_dissatisfaction += dissatisfaction_for_line return total_dissatisfaction if __name__ == "__main__": result = solve_gaokao_problem() print(result) ``` #### 关键点解析 上述代码实现了对学生估分学校分数线的处理逻辑,具体如下: - **输入读取**:程序从标准输入流中获取 `n` 名学生估分以及 `m` 所学校预计分数线[^1]。 - **排序预处理**:为了提查询效率,在计算前先对学生成绩进行了排序[^2]。 - **核心函数定义 (`binary_search`)** - 利用了经典的二分查找技术定位到距离当前学校分数线最近的学生得分位置,并返回两者差值作为该条记录下的满意程度。 - 如果存在完全一致的成绩,则直接返回零表示无任何满度增加。 最终累加每所学校对应的最佳匹配产生的满意数值并输出结果。 #### 复杂度分析 时间复杂度主要由以下几个部分构成: - 排序阶段的时间开销为 \(O(n \log n)\); - 每次针对单个学校执行一次二分查找所需时间为 \(O(\log n)\),因此对于全部 \(m\) 条记录总计耗时约为 \(O(m \cdot \log n)\). 综合来看整体性能表现良好适合较大规模的数据集运算需
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值