蓝桥杯国赛真题【分考场】
题意
思路
由于数据比较小,而且题意中的“认识”仅限于两个人之间,没有传递的意思,我们可以用爆搜来写,具体来看,我们先准备至少n个考场,从第一位考生开始爆搜。对于当前枚举的考生x,我们有两种选择,第一个:我们将当前考生放置已经存在考生的考场y(枚举已经存在考生的考场)中,满足该选择的条件是:考场y中的所有考生和当前枚举的考生均不认识。第二个:我们使用一个没有考生的教室z,将当前考生x放入进考场z。
算法
具体实现的话,我们用爆搜即可,定义函数void dfs(int u, int cnt)
,其中u
是当前枚举的考生,cnt
是用了多少个考场,两种情况对应在代码中寻找即可,这里额外讲一下本题的重点,如果当前使用的考场不小于我们的答案,我们应该立即返回,即在dfs
函数中return
,这是一个很优秀的剪枝技巧,此外,如果本题的剪枝条件为:使用的考场大于我们的答案。会导致本题最后一个样例因为超时而过不了本题,所以我们应当选用尽可能优秀的剪枝。
AC代码(C++)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 110;
int n, m, res = N;
bool re[N][N];
vector<int> rooms[N];
void dfs(int u, int cnt) {
if(cnt >= res) return ;
if(u == n + 1) {
res = cnt;
return ;
}
for(int i = 1; i <= cnt; i ++) { // 枚举当前考场是否可以放入u号考生
bool flag = true;
for(int j = 0; j < rooms[i].size(); j ++) {
if(re[u][rooms[i][j]]) {
flag = false;
break;
}
}
if(flag) {
rooms[i].push_back(u);
dfs(u + 1, cnt);
rooms[i].pop_back();
}
}
rooms[cnt + 1].push_back(u);
dfs(u + 1, cnt + 1);
rooms[cnt + 1].pop_back();
}
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i ++) re[i][i] = true;
while(m --) {
int a, b;
cin >> a >> b;
re[a][b] = re[b][a] = true;
}
dfs(1, 0);
cout << res << "\n";
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)