在校园招聘季节里,已知有n位学生,他们分别对m个研究组中的若干个感兴趣。为了满足所有的学生需求,如果每个见面会的时间是t,如何安排才能使得所有见面会总时间最短?
这是来自《编程之美》的第57页的一道题,具体的做法如下:
1.A同学对1,2,3小组感兴趣,写成A(1,2,3) B同学对1,3,4小组感兴趣,写成B(1,3,4) 转化为图如下:
2.这个问题转化为给图染色,有边的两节点染色要不一致,最少使用多少种颜色
3.针对这个问题,《编程之美》给出了两种解法,一种解法时间复杂度较大,另一种较小,但是都没有给出详细的代码,只给了思路(估计代码比较冗长吧),现在的话呢,我这里给出自己想到的一种解法(不对就多多指教)。
我的思路:
1.把结点想成二维数组中的元素,起先所有结点都在二维数组的第0列,如下图:
1 | ||
2 | ||
3 | ||
4 |
2.1号结点和2号节点在同一列上,而它们之间是有边的,所以将1号节点右移一个单
元
1 | |||
2 | |||
3 | |||
4 |
此时1所在的列没有和1结点相连的结点元素(下面全为空),所以1元素就移好了
再看2号元素,在第0列中,3元素是与2元素相连的,所以2号元素右移,如下
1 | |||
2 | |||
3 | |||
4 |
然而此时2号元素与刚刚的1号元素在同一列中,且1与2之间是有边的,所以2继续右移
1 | |||
2 | |||
3 | |||
4 |
这时候2就安全了
同理,3移动后
1 | |||
2 | |||
3 | |||
4 |
最后一个元素不管能不能在所在的列容下身,都必须右移,因为最后一个元素可能插到空里头,所以最后如下:
1 | |||
2 | |||
3 | |||
4 |
移动元素部分就完成了,接下来分析这个二维数组:
每一列就是一种颜色,总共有3列有元素的列,所以一共需要三种颜色,1一种颜色,2,4一种颜色,3一种颜色。
另:实际上没必要造一个数组,用一个哈希表就行了,key纪录节点的值,value纪录结点所在的列,所以文章的标题是:虚拟二维数组求染色问题 下面是我的代码 java写的:
package test;
import java.util.*;
public class Test
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
System.out.println("地图有几个区域?");
int n = sc.nextInt();
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0;i<n;i++)
{
map.put(i, 0);
}
int[][] a = new int[n][n];
for(int i = 0;i<n;i++)
{
System.out.println("第"+i+"个区域有几个相邻区域?");
int m = sc.nextInt();
System.out.println("依次输入与第"+i+"个区域相邻的区域号");
for(int j = 0;j<m;j++)
{
a[i][sc.nextInt()] = 1;
}
}
for(int i = 0;i<n;i++)
{
boolean hasMoved = true;
if(i == n-1)
map.put(n-1, 1);
while(hasMoved)
{
hasMoved = false;
for(int j = 0;j<n;j++)
{
if( (a[i][j] == 1||a[j][i] == 1)
&&map.get(j) == map.get(i))
{
map.put(i, map.get(i)+1 );
hasMoved = true;
break;
}
}
}
}
for(int i = 0;i<n;i++)
{
System.out.println("第"+i+"号区域涂上第"+map.get(i)+"号颜色");
}
}
}
对于图:
输入输出如下:
地图有几个区域?
6
第0个区域有几个相邻区域?
3
依次输入与第0个区域相邻的区域号
1 2 3
第1个区域有几个相邻区域?
4
依次输入与第1个区域相邻的区域号
0 2 4 5
第2个区域有几个相邻区域?
4
依次输入与第2个区域相邻的区域号
0 1 3 4
第3个区域有几个相邻区域?
3
依次输入与第3个区域相邻的区域号
0 2 4
第4个区域有几个相邻区域?
4
依次输入与第4个区域相邻的区域号
1 2 3 5
第5个区域有几个相邻区域?
2
依次输入与第5个区域相邻的区域号
1 4
第0号区域涂上第1号颜色
第1号区域涂上第2号颜色
第2号区域涂上第3号颜色
第3号区域涂上第2号颜色
第4号区域涂上第1号颜色
第5号区域涂上第3号颜色
对于图:
输入输出如下:
地图有几个区域?
7
第0个区域有几个相邻区域?
3
依次输入与第0个区域相邻的区域号
1 2 3
第1个区域有几个相邻区域?
3
依次输入与第1个区域相邻的区域号
0 2 5
第2个区域有几个相邻区域?
5
依次输入与第2个区域相邻的区域号
0 1 3 4 5
第3个区域有几个相邻区域?
3
依次输入与第3个区域相邻的区域号
0 2 4
第4个区域有几个相邻区域?
4
依次输入与第4个区域相邻的区域号
2 3 5 6
第5个区域有几个相邻区域?
4
依次输入与第5个区域相邻的区域号
1 2 4 6
第6个区域有几个相邻区域?
2
依次输入与第6个区域相邻的区域号
4 5
第0号区域涂上第1号颜色
第1号区域涂上第2号颜色
第2号区域涂上第3号颜色
第3号区域涂上第2号颜色
第4号区域涂上第1号颜色
第5号区域涂上第4号颜色
第6号区域涂上第2号颜色