蓝桥杯练习–分考场(回溯递归)
题目:
n个人参加某项特殊考试。为了公平,要求任何两个认识的人不能分在同一个考场。
求至少需要分几个考场才能满足条件。
输入格式:
第一行,一个整数n(1<n<100),表示参加考试的人数。
第二行,一个整数m,表示接下来有m行数据
以下m行每行的格式为:两个整数a,b,用空格分开 (1<=a,b<=n) 表示第a个人与第b个人认识。
输出格式:
一行一个整数,表示最少分几个考场。
思路:
这道题是一道看起来不太简单的题,但只要有了明白的解题思路,一切就很好办了。首先很容易想到的方法就是n个学生,从1号开始到n号,每一位学生都遍历一遍已经分好的考场,如果没有认识的,就在这个考场加入此学生,若有认识的就换到下一个考场判断。若都有认识的就添加一个新的考场(初始考场数量为0),每当安排好所有学生后if看一下是否最小值,回溯接着找。
其中必须想到剪枝,否则会超时。在回溯过程中,只要比最小值大于或等于,则直接返回,继续另一种安排。
然后数据结构为了编程的方便,选择合适的数据结构。这里考场用c++中STL库中的vector不定长数组,方便对学生id在考场中的增加于删减。
#include <iostream>
#include <vector>
#include <algorithm>
#define inf 999999
using namespace std;
int n,m,minclassroom=inf;
int stumap[101][101]={0};
vector <int> room[101];
void dfs(int id,int roomnum)
{
int i,j;
if(roomnum>=minclassroom)
{
return;
}
if(id==n+1)
{
minclassroom=(minclassroom,roomnum);
return;
}
for(i=1;i<=roomnum;i++)
{
int flag=1;
for(j=0;j<room[i].size();j++)
{
if(stumap[room[i][j]][id]==1)
{
flag=0;
break;
}
}
if(flag==1)
{
room[i].push_back(id);
dfs(id+1,roomnum);
vector<int>::iterator it=room[i].end();
it--;
room[i].erase(it);
}
}
room[roomnum+1].push_back(id);
dfs(id+1,roomnum+1);
vector<int>::iterator it=room[i].end();
it--;
room[roomnum+1].erase(it);
return;
}
int main()
{
int a,b,i;
cin>>n>>m;
for(i=1;i<=m;i++)
{
cin>>a>>b;
stumap[a][b]=1;
stumap[b][a]=1;
}
dfs(1,0);
cout<<minclassroom<<endl;
return 0;
}