分考场

原创


问题描述
  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
一个无向图着色,要求相邻的点不能是同色,方案有多种,找出所用颜色数最少的方案即可解题。
  着色过程是按点顺序一一着色,n个点,一一按顺序为点1~n着色,着色完一个点继续着色下一个点,直至着色完n个点。
  由于一个点可以多种合理的着色方案,不同的着色方案对最终的颜色种数影响是不同的,所以需要一一比较所有的方案,过程类似
深搜回溯。
 1 import java.util.*;
 2 
 3 public class Main {
 4     
 5     static int n;    //考试人数
 6     static int m;    //m个关系
 7     static int matrix[][];    //邻接矩阵
 8     static int max=0;    //用了的颜色数
 9     static int pid_Color[];    //存储点用了哪种颜色
10     static int flag=0;
11     static int res=99999;
12     
13     static boolean judge(int pid,int color) {
14         for(int i=1;i<=n;i++) {
15             //邻接点判断
16             if(matrix[pid][i]==1) {
17                 //判断邻接点是否涂色
18                 if(pid_Color[i]!=0) {
19                     //邻接点颜色判断
20                     if(pid_Color[i]==color) {
21                         return false;
22                     }
23                 }
24             }
25         }
26         return true;
27     }
28     
29     static void color_Painting(int pid,int color_Num) {    //pid代表点,目前已经用了color_Num种颜色
30         if(color_Num>=res) {
31             return;
32         }
33         if(pid>n) {
34             res=res<color_Num?res:color_Num;
35             return;
36         }
37         //枚举颜色1~color_Num,看看可不可以用在点pid
38         for(int color=1;color<=color_Num;color++) {
39             //可以
40             if( judge(pid,color)==true ) {
41                 pid_Color[pid]=color;    //涂色
42                 color_Painting(pid+1,color_Num);//涂下一个点
43                 pid_Color[pid]=0;
44             }
45         }
46         //颜色1~color_Num都用不了,用新的颜色
47         pid_Color[pid]=color_Num+1;
48         color_Painting(pid+1,color_Num+1);
49         pid_Color[pid]=0;
50     }
51 
52     public static void main(String[] args) {
53         Scanner reader=new Scanner(System.in);
54         n=reader.nextInt();
55         m=reader.nextInt();
56         matrix=new int[n+1][n+1];    //编号从1开始
57         pid_Color=new int[n+1];
58         //读入m个关系
59         for(int i=1;i<=m;i++) {
60             int a=reader.nextInt();
61             int b=reader.nextInt();
62             //无向图
63             matrix[a][b]=1;
64             matrix[b][a]=1;
65         }
66         color_Painting(1,0);
67         System.out.println(res);
68     }
69 }

  代码2:

 1 import java.util.*;
 2 
 3 public class Main {
 4     
 5     static int n;    //学生人数
 6     static int m;    //关系
 7     //邻接矩阵
 8     static int matrix[][];
 9     //room[i][j]=z代表教室room[i]的第j个座位坐着同学z
10     static int room[][];
11     //room_num[i]存储教室room[i]目前坐了多少位同学
12     static int room_num[];
13     static int res=1000;
14     
15     static void sit(int stu,int pos) {    //stu表示第stu个学生,pos表示目前用了pos个教室
16         if(pos>=res) {
17             return;
18         }
19         if(stu>n) {
20             res=res<pos?res:pos;
21             return;
22         }
23         //判断前面1~pos个教室能不能放入同学stu
24         for(int i=1;i<=pos;i++) {
25             //对于教室room[i],只要同学stu不认识里面的其他所有同学即可放入,可以判断stu在此教室不认识的人数是否等于room_num[i]
26             int total=0;    //统计stu在此教室room[i]不认识的人数
27             for(int j=1;j<=room_num[i];j++) {
28                 if(matrix[stu][room[i][j]]==0) {
29                     total++;
30                 }
31             }
32             //stu不认识教室room[i]里面的所有人
33             if(total==room_num[i]) {
34                 room[i][++room_num[i]]=stu;    //放入stu
35                 sit(stu+1,pos);    //考虑下一位同学,因为没有开辟新的教室,所以还是只用了pos个教室
36                 //回溯的原因:学生stu虽然可以放在教室room[a],但也许可以放入room[b],这两种放法对所需开辟的最小教室量是不同的,所以需要枚举所有情况
37                 room_num[i]--;
38             }
39         }
40         //来到此步,说明教室1~pos都放不下学生stu,必须开辟新的教室
41         room[pos+1][1]=stu;    //将stu放入新的教室
42         room_num[pos+1]++;
43         sit(stu+1,pos+1);
44         room_num[pos+1]--;    //回溯
45     }
46 
47     public static void main(String[] args) {
48         Scanner reader=new Scanner(System.in);
49         n=reader.nextInt();
50         m=reader.nextInt();
51         matrix=new int[n+1][n+1];
52         room=new int[101][101];
53         room_num=new int[101];
54         //读入边
55         for(int i=1;i<=m;i++) {
56             int one=reader.nextInt();
57             int two=reader.nextInt();
58             matrix[one][two]=1;
59             matrix[two][one]=1;
60         }
61         sit(1,0);
62         System.out.println(res);
63     }
64 
65 }

16:53:43

2018-08-11

原文地址:https://www.cnblogs.com/chiweiming/p/9459726.html