有的女生

有的女生就像Windows 虽然很优秀,但是安全隐患太大。
有的女生就像UNIX  她条件很好,然而不是谁都能玩的起。
有的女生就像C# 长的很漂亮,但是家务活不行。
有的女生就像C++,她会默默的为你做很多的事情。
有的女生就像JAVA,只需一点付出她就会为你到处服务。
有的女生就像JAVA script,虽然对她处处小心但最终还放不了。
真正爱上一个人的时候,那就是常量限定,永远不会改变。
女朋友就是私有变量,只有我这个类才能调用。
情人就是指针用的时候一定要注意,要不然就带来巨大的灾难。

我们来解决这个 **宿舍分配问题**,这是一个结合了 **数学约束分析和枚举优化** 的编程题。 --- ### ✅ 题目要求(重述与提炼) 给定: - 女生人数 `n0` - 男生人数 `n1` - 寝室总数 `n` 要将所有寝室分完,且满足以下规则: 1. **男女生不能混住** → 分成两个独立的寝室区 2. **不允许单人住一间寝室** → 每间寝室 ≥2 人 3. **同性别每间寝室人数必须相同** → 女生:`k0` 人/间,男生:`k1` 人/间(整数 ≥2) 4. 在有多个解时,选择 `|k0 - k1|` 最小的方案 5. 所有寝室必须用完,所有人必须安排 输出: - 女生分配的寝室数 `r0` 和男生分配的寝室数 `r1`,即 `r0 r1` - 若无解,输出 `No Solution` --- ## 🔍 解题思路 设: - 女生住 `r0` 间寝室,则男生住 `r1 = n - r0` 间 - 每间女生寝室住 `k0 = n0 / r0` 人 → 要求 `r0 > 0` 且 `n0 % r0 == 0` - 每间男生寝室住 `k1 = n1 / r1` 人 → 要求 `r1 > 0` 且 `n1 % r1 == 0` - 并且:`k0 >= 2`, `k1 >= 2` 我们要遍历所有可能的 `r0`(从 1 到 n-1),尝试找出合法解,并从中选出使 `|k0 - k1|` 最小的那个。 > 注意:`r0=0` 或 `r1=0` 是不允许的!因为如果某一性别没分到寝室: > - 如果 `n0 > 0` 但 `r0 = 0` → 女生没地方住 ❌ > - 同理,`n1 > 0` 但 `r1 = 0` 也不行 > - 所以:只有当 `n0 == 0` 时才允许 `r0 = 0`,否则不行 但我们题目说“等待分配的学生中有女生 n₀ 位、男生 n₁ 位”,并未说明是否为 0。所以要考虑边界情况。 不过题目也说了:“所有待分配学生都必须分到一间寝室”、“所有寝室都要分出去”。 --- ## ✅ 算法步骤 1. 枚举女生寝室数量 `r0` 从 `max(0,?)` 到 `min(n, n0)`,但注意: - `r0` 必须满足:`r0 >= 1` 如果 `n0 > 0`;若 `n0 == 0`,则 `r0 = 0` - 同理 `r1 = n - r0 >= 1` 如果 `n1 > 0`;若 `n1 == 0`,则 `r1 = 0` 2. 对每个 `r0`: - 计算 `r1 = n - r0` - 检查合法性: - `r0 == 0` 只能在 `n0 == 0` - `r1 == 0` 只能在 `n1 == 0` - `r0 > 0` ⇒ `n0 % r0 == 0` 且 `k0 = n0 / r0 >= 2` - `r1 > 0` ⇒ `n1 % r1 == 0` 且 `k1 = n1 / r1 >= 2` 3. 收集所有合法方案,记录对应的 `|k0 - k1|` 4. 选择差值最小的一个 5. 如果没有合法方案,输出 `No Solution` --- ## ✅ C++ 实现代码 ```cpp #include <iostream> #include <climits> #include <cstdlib> using namespace std; int main() { int n0, n1, n; cin >> n0 >> n1 >> n; int best_r0 = -1; int minDiff = INT_MAX; // 枚举女生寝室数量 r0 for (int r0 = 0; r0 <= n; r0++) { int r1 = n - r0; // 检查 r0 和 r1 是否合理(根据人数) if (n0 == 0) { if (r0 != 0) continue; } else { if (r0 == 0) continue; // 女生有人却没分寝室 } if (n1 == 0) { if (r1 != 0) continue; } else { if (r1 == 0) continue; // 男生有人却没分寝室 } // 检查女生寝室是否合法:能整除且每间至少2人 if (r0 > 0) { if (n0 % r0 != 0) continue; int k0 = n0 / r0; if (k0 < 2) continue; } // 检查男生寝室是否合法 if (r1 > 0) { if (n1 % r1 != 0) continue; int k1 = n1 / r1; if (k1 < 2) continue; } // 当前方案合法,计算 |k0 - k1| int k0 = (r0 == 0) ? 0 : n0 / r0; int k1 = (r1 == 0) ? 0 : n1 / r1; int diff = abs(k0 - k1); // 更新最优解 if (diff < minDiff) { minDiff = diff; best_r0 = r0; } } // 输出结果 if (best_r0 == -1) { cout << "No Solution" << endl; } else { cout << best_r0 << " " << (n - best_r0) << endl; } return 0; } ``` --- ## 🧪 示例测试 ### 输入样例 1: ``` 24 60 10 ``` 枚举 `r0` 从 0 到 10: 找一个合法组合: 假设 `r0 = 4`, `r1 = 6` - 女生:24 ÷ 4 = 6 人/间 ✅ ≥2 - 男生:60 ÷ 6 = 10 人/间 ✅ ≥2 - 差值:|6 - 10| = 4 再试其他? `r0 = 3` → 24÷3=8,r1=7 → 60%7≠0 ❌ `r0 = 6` → 24÷6=4,r1=4 → 60÷4=15 → |4-15|=11 `r0 = 8` → 24÷8=3,r1=2 → 60÷2=30 → |3-30|=27 `r0 = 12`?超了,n=10,不行 我们发现 `r0=4` 是唯一能让两者都整除的吗? 试试 `r0=6`: 24÷6=4 ✅, r1=4: 60÷4=15 ✅ → diff=11 `r0=3`: 24÷3=8 ✅, r1=7: 60%7≠0 ❌ `r0=2`: 24÷2=12 ✅, r1=8: 60%8=4 ≠0 ❌ `r0=1`: 不允许(单人住)→ 24人/1间 = 24 ≥2,但只有一间?可以吗? ⚠️ 注意:`r0=1` → 24人住一间,是允许的!只要不是“单人住”就行。“单人住”意思是每间1人,而不是总寝室数为1。 但是题目说的是:“不允许单人住一间寝室” → 即每间人数 ≥2,不是说不能只有一个寝室! 所以 `r0=1` 是允许的,只要 `n0 >= 2`。 继续检查: `r0=4` → k0=6, k1=10 → diff=4 `r0=6` → k0=4, k1=15 → diff=11 `r0=8` → 24÷8=3 ✅, r1=2 → 60÷2=30 ✅ → diff=27 `r0=12` 超过 n=10,无效 另一个:`r0=3` → 24÷3=8, r1=7 → 60%7≠0 ❌ `r0=5` → 24%5≠0 ❌ `r0=7` → 24%7≠0 ❌ `r0=9` → 24%9=6≠0 ❌ `r0=10` → 24%10=4≠0 ❌ 所以只有几个可行: - `r0=4`: diff=4 - `r0=6`: diff=11 - `r0=8`: diff=27 最小差值是 `4`,对应 `r0=4`, `r1=6` ✅ 输出: ``` 4 6 ``` 符合预期! --- ## ⚠️ 特殊情况处理 | 情况 | 是否处理 | |------|---------| | n0=0 | ✅ 处理了,强制 r0=0 | | n1=0 | ✅ 强制 r1=0 | | 无法整除 | ✅ 跳过 | | 每间<2人 | ✅ 检查 k>=2 | | 无任何合法方案 | ✅ 输出 No Solution | --- ## ✅ 时间复杂度分析 - 枚举 `r0` 从 0 到 n,最多 1e5 次 - 每次 O(1) 判断 - 总体 O(n),可接受 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值