zoukankan      html  css  js  c++  java
  • 历届试题 分考场

    问题描述

      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
    样例输入
    5
    10
    1 2
    1 3
    1 4
    1 5
    2 3
    2 4
    2 5
    3 4
    3 5
    4 5
    样例输出
    5
    思路:我的第一个思路是用贪心法是指从第一个同学开始分配考场,然后遍历后面的学生如果和第一个同学不认识,并且不和这个房间其余的学生认识,那么他就可以加进来,第一个考场加入学生完毕。在从第二个没有分配考场的学生分配考场,按照同样的方法该考场加入学生,依次类推。最终结果发现只通过两组测试用例,分析结果不对的原因是贪心法不保证结果是最优的,所以考场数不是最少的。先把代码贴出来,希望以后看到能反思。
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int Amap[1001][1001];
     4 int p[1001];
     5 vector<int> a[1001];
     6 int n,m;
     7 int main()
     8 {
     9     cin >> n >> m;
    10     int a1,a2;
    11     memset(Amap,0,sizeof(Amap));
    12     memset(p,0,sizeof(p));
    13     for(int i=1;i<=m;i++){
    14         cin >> a1 >> a2;
    15         Amap[a1][a2]=1;
    16         //Amap[a2][a1]=1;
    17     }
    18     int num=0;
    19     int flag;
    20     for(int i=1;i<=n;i++){
    21             if(p[i]==1) continue;
    22 
    23            //  cout << i <<" ";
    24         for(int j=i+1;j<=n;j++){
    25                 if(i==j) continue;
    26                 flag=0;
    27             if(Amap[i][j]==0&&Amap[j][i]==0&&p[j]==0){
    28 
    29             for(vector<int>::iterator iter=a[i].begin();iter!=a[i].end();++iter){
    30                 if(Amap[*iter][j]==1 || Amap[j][*iter]==1) flag=1;
    31             }
    32             if(flag==0){
    33                 a[i].push_back(j);
    34            // cout << j << " ";
    35                 p[j]=1;
    36             }
    37             }
    38         }
    39              //cout << endl;
    40         p[i]=1;
    41         num++;
    42 
    43     }
    44     cout << num << endl;
    45     return 0;
    46 }

    百度之后可以考虑使用dfs,

    每新加进来一个人,都与已经开设的教室里面的人进行对比,如果找到一个教室满足,教室里面所有的人都不和新加入的人认识,那么就考虑将这个人加进来。再回溯。最后,当所有教室都不满足的时候,新增教室。参考代码如下

      1 #include<iostream>
      2 
      3 #include<vector>
      4 
      5 using namespace std;
      6 
      7 #define MAXN 110
      8 
      9 #define INF 0x3f3f3f3f;
     10 
     11 int graph[MAXN][MAXN];//建立图
     12 
     13 int cun[MAXN][MAXN];//存储第几个教师有谁谁谁
     14 
     15 int cnt[MAXN]={0};//记录每个教室的人数
     16 
     17 int res=INF;//假设需要一个无穷多的教室
     18 
     19 int n,m;//定义人数,以及认识的数目
     20 
     21 void solve(int id,int num)//回溯搜索,id表示当前安排的是第id的同学,num表示当前安排这个id同学的时时候已经用了多少个教室
     22 
     23 {
     24 
     25         if(num>=res)//如果当前的教室方案已经超过以前的方案了,那么就放弃返回
     26 
     27         return;
     28 
     29     if(id>n)//如果说id的同学的id>n说明全部的同学都安排完了
     30 
     31         {
     32 
     33         res=num;//如果执行到这一步说明res一定是.>num的,所以更新一下
     34 
     35         return;//返回
     36 
     37         }
     38 
     39     for(int i=0;i<num;i++)//扫描每一个已经存在的教室
     40 
     41     {
     42 
     43         int len=cnt[i];//取一下当前i教室的人数
     44 
     45         int c=0;//这个变量表示当前id的同学和这个教室的同学不认识的人数
     46 
     47         for(int j=0;j<len;j++)//扫描这个教室的每一个同学
     48 
     49         {
     50 
     51             if(graph[id][cun[i][j]]==0)//如果没有关系
     52 
     53                 c++;//加1
     54 
     55         }
     56 
     57         if(c==len)//如果全部不认识
     58 
     59         {
     60 
     61             cun[i][cnt[i]++]=id;//那么id同学就进入这个教室,同时这个教室的人数+1
     62 
     63             solve(id+1,num);//那么安排下一个教室
     64 
     65             cnt[i]--;//递归返回之后把这个同学在从这个教室分走,分到下几个教室看看
     66 
     67         }
     68 
     69     }
     70 
     71     cun[num][cnt[num]++]=id;//如果全部教室都存在id认识的同学,那么就把这个同学新开个教室
     72 
     73     solve(id+1,num+1);//递归下一个同学并且当前的教室数目+!
     74 
     75     cnt[num]--;//返回后移除这个同学看下上一个同学有没有其他的选择
     76 
     77 }
     78 
     79 int main()
     80 
     81 {
     82 
     83     cin>>n>>m;
     84 
     85     for(int i=0;i<m;i++)
     86 
     87     {
     88 
     89         int a,b;
     90 
     91         cin>>a>>b;
     92 
     93         graph[a][b]=1;
     94 
     95         graph[b][a]=1;//如果两个人认识的话就可以标记成1,c++在数组创建 的时候已经快速初始化
     96 
     97     }
     98 
     99     solve(1,0);//进入回溯更新最小的教室数目
    100 
    101     cout<<res;//输入所有可能中的最小的答案
    102 
    103 }
  • 相关阅读:
    Pycharm5使用
    flask 分页
    CRM
    课程项目
    vue的属性指令
    vue的文本指令
    vue实例
    vue使用
    ajax的json格式数据
    django知识点小结
  • 原文地址:https://www.cnblogs.com/henuliulei/p/10548685.html
Copyright © 2011-2022 走看看