试题 历届试题 分考场——图解+详细分析

题目链接:传送门(点我)

分析:可否贪心,不可,如果枚举每个人,如果发现一个队伍里面和他不认识就放进去,可否是最优解?不一定。也许放后面情况更优?对于这种关系不好理清,我选择枚举。
其实DFS就是一种层数不定的枚举。

在这里插入图片描述
在这里插入图片描述

搜索就是产生解答树的过程,而回溯是回溯当前改变的状态。也就是回到改变之前的状态 可以参考我这个题的题解。传送门(点我)

那么如果枚举的话,对于一个人,他可能有几种状态。

  1. 加入某个房间
  2. 自己新开一个房间
    于是解答树应该按照这种逻辑展开
    在这里插入图片描述
    设计dfs函数时,每一层dfs就是一种状态,而全局变量room是为了避免每层dfs里面都来记录room状态浪费空间,所以回溯的时候对全局变量room操作即可。

关于剪枝:由于我们知道,深度优先搜索的解答树是 深度优先, 也就是说,当我们第一次找到一种方案,之后的如果比前面方案情况更差(房间数更多),我们就不需要对那棵树(情况)进行展开继续下去了。

#include<bits/stdc++.h>
using namespace std;
#define MAXN 105

int n,m,a,b,res=0x7fffffff;
bool relation[MAXN][MAXN];//关系,是否认识
vector<int>room[MAXN];//存储房间当前的学生

void add(int a,int b){relation[a][b]=1;relation[b][a]=1;}

void dfs(int id,int num)
{
    if(num>=res)return;
    if(id>n){res=min(num,id);return;}
    for(int i=1;i<=num;i++){//尝试现在有的所有房间
        int flag=0;
        for(int j=0;j<room[i].size();j++){//遍历房间
            if(relation[id][room[i][j]]){//如果有认识的人
                flag=1;
                break;
            }
        }
        if(!flag){//都不认识
            room[i].push_back(id);
            dfs(id+1,num);
            room[i].pop_back();
        }
    }
    //不加入房间
    room[num+1].push_back(id);
    dfs(id+1,num+1);
    room[num+1].pop_back();

}

int main()
{
    cin>>n>>m;
    while(m--){
        cin>>a>>b;
        add(a,b);
    }
    dfs(1,0);
    return cout<<res<<endl,0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值