蓝桥杯历届试题 - 分考场(DFS+剪枝)

链接:历届试题 - 分考场

问题描述

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



分析:

因为n<100,所以用DFS暴力即可,不过要剪枝

对于一个人,要么 放入已有的考场(前提是该考场没有其认识的人),要么 放入一个新考场。以这样的思路的DFS就行。

可以用vector来操作,虽然方便,不过遍历速度会慢些。



以下代码:

#include<cstdio>
#include<vector>
#include<algorithm>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=110;
int n,m,ans=INF;
bool G[maxn][maxn]={false};    //G[a][b]为1表示a,b认识,为0表示a,b不认识
vector<int>	room[maxn];        //表示考场
void DFS(int i,int j)          //i表示当前处理的人的编号,j表示考场数
{
	if(j>=ans)                 //剪枝
		return;
	if(i>n)                    //i>n说明已处理完所有人
	{	
		ans=min(ans,j);
		return;
	}
	//放入已有考场
	for(int k=1;k<=j;k++)
	{
		bool ok=true;
		for(int l=0;l<room[k].size();l++)
		{
			if(G[room[k][l]][i])
			{
				ok=false;
				break;
			}
		}
		if(ok)
		{
			room[k].push_back(i);
			DFS(i+1,j);
			room[k].pop_back();   //别忘了这个
		}
	}
	//放入新考场
	room[j+1].push_back(i);
	DFS(i+1,j+1);
	room[j+1].pop_back();          //也别忘了这个
}
int main()
{	
	scanf("%d %d",&n,&m);
	int a,b;
	while(m--)
	{
		scanf("%d %d",&a,&b);
		G[a][b]=true;
		G[b][a]=true;
	}
	DFS(1,0);
	printf("%d",ans);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值