分考场(蓝桥杯)

文章目录

分考场

题目描述

n 个人参加某项特殊考试。

为了公平,要求任何两个认识的人不能分在同一个考场。

求最少需要分几个考场才能满足条件。

输入描述

输入格式:

第一行,一个整数 n (1≤n≤100),表示参加考试的人数。

第二行,一个整数 m,表示接下来有 m 行数据。

以下 m 行每行的格式为:两个整数 ,a,b,用空格分开 ( 1≤a,b≤n )表示第 a 个人与第 b 个人认识。

输出描述

输出一行一个整数,表示最少分几个考场。

输入输出样例

示例

输入

复制代码
5
8
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5

输出

复制代码
4  

dfs

解题思路

  1. 决策类型的搜索,使用dfs进行决策搜索
  2. 两个人之间的认识关系可以使用邻接矩阵进行存储,如果认识加一条无向边即可
  3. dfs枚举的是每个人,check现存的每一个考场,此人依次尝试进可加入的考场,尝试新开一个考场加入,也可考虑剪枝优化

代码

这段代码是用来解决考场分配问题的。具体而言,它需要确保认识的人不能分配到同一个考场。程序通过深度优先搜索(DFS)算法来寻找满足条件的最小考场数。以下是对代码的详细注释:

cpp 复制代码
#include<iostream>
#include<vector> 
using namespace std;
const int N = 110;

bool g[N][N]; // 使用邻接矩阵来表示人与人之间的认识关系,如果g[i][j]为true,则代表第i个人与第j个人认识。

vector<int> q[N]; // 使用一个向量数组q来存储每个考场中已分配的人员名单。

int ans = 100; // 初始化答案为100,这是一个上限值,因为最多有100个人,所以最多需要100个考场。

int n, m; // n代表人数,m代表已知的认识关系对数量。

// 检查某个人是否能够被分配到某个考场。
bool check(int b, int i) {
    for (int j = 0; j < q[i].size(); j++) // 遍历当前考场中的所有人。
        if (g[b][q[i][j]]) // 如果b与考场中的某个人认识,则返回false。
            return false;
    return true; // 如果b与考场中任何人都不认识,则可以分配到这个考场,返回true。
}

// DFS函数,于搜索所有可能的分配方案。
void dfs(int now, int cnt) {
    if (cnt >= ans) // 如果当前方案使用的考场数已经不小于当前找到的最小值,则停止搜索这条路径。
        return;
    
    if (now == n + 1) { // 如果所有人都已经被分配考场,更新最小考场数。
        ans = min(ans, cnt);
        return;
    }

    for (int p = 1; p <= cnt; p++) { // 尝试将当前人分配到现有的每个考场。
        if (check(now, p)) { // 如果可以分配到当前考场。
            q[p].push_back(now); // 将当前人加入到考场p中。
            dfs(now + 1, cnt); // 继续搜索下一个人的分配方案。
            q[p].pop_back(); // 回溯,将当前人从考场p中移除。
        }
    }

    // 尝试开设新的考场,并将当前人分配进去。
    if (cnt + 1 <= n) {
        q[cnt + 1].push_back(now); // 在新考场加入当前人。
        dfs(now + 1, cnt + 1); // 继续搜索下一个人的分配方案,并增加考场数。
        q[cnt + 1].pop_back(); // 回溯,将当前人从新考场中移除。
    }
}

int main() {
    cin >> n >> m; // 输入总人数和认识关系对数量。
    int a, b;
    for (int i = 0; i < m; i++) {
        cin >> a >> b; // 输入认识关系对。
        g[a][b] = g[b][a] = 1; // 在邻接矩阵中标记双向认识关系。
    }
    dfs(1, 1); // 从第1个人开始深度优先搜索,并尝试将其放入第一个考场。
    cout << ans << endl; // 输出最少需要的考场数。
    return 0;
}

代码首先读入参加考试的人数n和认识关系对数,然后读入每对认识关系并在邻接矩阵g中标记。主要逻辑在dfs函数中,它尝试所有可能的人员分配方案来寻找使用最少考场数的方案。搜索过程中,如果发现当前方案使用的考场数已经达到或超过了之前找到的最小值,则停止继续搜索该路径。当所有人都被成功分配到考场后,会更新最少需要的考场数。最终,程序输出找到的最小值作为答案。

相关推荐
极地星光2 小时前
C++链式调用设计:打造优雅流式API
服务器·网络·c++
小陈要努力3 小时前
Visual Studio 开发环境配置指南
c++·opengl
程序猿本员3 小时前
5. 实现
c++
Bona Sun3 小时前
单片机手搓掌上游戏机(十五)—pico运行fc模拟器之编译环境
c语言·c++·单片机·游戏机
小尧嵌入式4 小时前
C++基础语法总结
开发语言·c++·stm32·单片机·嵌入式硬件·算法
white-persist4 小时前
【攻防世界】reverse | IgniteMe 详细题解 WP
c语言·汇编·数据结构·c++·python·算法·网络安全
你的冰西瓜4 小时前
C++20 新特性详解:相较于 C++17 的主要改进
开发语言·c++·stl·c++20
止观止4 小时前
C++20 Ranges:告别手写循环,像 SQL 一样操作数据
c++·stl·c++20·编程范式·ranges
郝学胜-神的一滴5 小时前
现代OpenGL窗口管理:GLFW从入门到实战
开发语言·c++·程序人生·图形渲染·个人开发
Bona Sun6 小时前
单片机手搓掌上游戏机(十六)—pico运行fc模拟器之程序修改烧录
c语言·c++·单片机·游戏机