P1056 排座椅 - 洛谷

这是一道信息学竞赛题目,要求设计程序找到最佳的课堂座位通道划分方案,以最少的通道隔开最多交头接耳的学生对。题目描述了教室的座位布局和通道设置规则,并给出了输入输出格式及样例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情。不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的D对同学上课时会交头接耳。

同学们在教室中坐成了 MM 行 NN 列,坐在第i行第j列的同学的位置是 (i,j)(i,j) ,为了方便同学们进出,在教室中设置了 KK条横向的通道, LL 条纵向的通道。

于是,聪明的小雪想到了一个办法,或许可以减少上课时学生交头接耳的问题:她打算重新摆放桌椅,改变同学们桌椅间通道的位置,因为如果一条通道隔开了 22 个会交头接耳的同学,那么他们就不会交头接耳了。

请你帮忙给小雪编写一个程序,给出最好的通道划分方案。在该方案下,上课时交头接耳的学生的对数最少。

输入输出格式

输入格式:

第一行,有 55 个用空格隔开的整数,分别是 M,N,K,L,D(2 \le N,M \le 1000,0 \le K<M,0 \le L<N,D \le 2000)M,N,K,L,D(2N,M1000,0K<M,0L<N,D2000)

接下来的 DD 行,每行有 

### P1056 座椅算法 C++ 实现 以下是基于问题描述以及参考资料中的核心思想设计的一个完整的 C++ 解决方案。该程序通过统计可能的切割位置并选取最优解来满足题目需求。 #### 代码实现 ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; struct State { int pos; // 切割位置(行号或列号) int count; // 对应位置上的交头接耳学生对数 }; bool cmp(const State &a, const State &b) { if (a.count != b.count) return a.count > b.count; return a.pos < b.pos; } int main() { int m, n, k, l, d; cin >> m >> n >> k >> l >> d; vector<int> x(m + 1, 0); // 行方向切割计数器 vector<int> y(n + 1, 0); // 列方向切割计数器 for (int i = 0; i < d; ++i) { int aa, ab, ba, bb; cin >> aa >> ab >> ba >> bb; if (aa == ba) { // 竖直切割 y[min(ab, bb)]++; } else { // 水平切割 x[min(aa, ba)]++; } } // 处理水平切割 vector<State> rows; for (int i = 1; i <= m; ++i) { if (x[i] > 0) { rows.push_back(State{i, x[i]}); } } sort(rows.begin(), rows.end(), cmp); vector<int> selected_rows; for (int i = 0; i < min((int)rows.size(), k); ++i) { selected_rows.push_back(rows[i].pos); } sort(selected_rows.begin(), selected_rows.end()); // 输出选中的行 for (size_t i = 0; i < selected_rows.size(); ++i) { cout << selected_rows[i]; if (i != selected_rows.size() - 1) cout << " "; } cout << endl; // 处理垂直切割 vector<State> cols; for (int j = 1; j <= n; ++j) { if (y[j] > 0) { cols.push_back(State{j, y[j]}); } } sort(cols.begin(), cols.end(), cmp); vector<int> selected_cols; for (int i = 0; i < min((int)cols.size(), l); ++i) { selected_cols.push_back(cols[i].pos); } sort(selected_cols.begin(), selected_cols.end()); // 输出选中的列 for (size_t i = 0; i < selected_cols.size(); ++i) { cout << selected_cols[i]; if (i != selected_cols.size() - 1) cout << " "; } cout << endl; return 0; } ``` #### 关键点解析 1. **数据结构的选择** 使用 `vector` 存储每一行和每一列的切割次数,便于动态扩展和访问[^1]。 2. **贪心策略的应用** 题目要求选择最多交头接耳学生的切割位置,因此采用贪心方法逐一挑选最大值,并将其标记为已处理状态。为了优化时间复杂度,引入自定义序函数 `cmp` 来加速寻找最佳切割位置的过程[^2]。 3. **输入输出细节** 根据题目说明,最终需按升序列输出选定的切割位置,这一步骤在代码中通过两次调用 `sort()` 函数完成[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值