蓝桥杯练习--分考场(回溯递归)

蓝桥杯练习–分考场(回溯递归)
题目:
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;
} 

猜你喜欢

转载自blog.csdn.net/HT24k/article/details/107255700