[算法]循环赛日程表
2013-08-22 19:15
197 查看
问题描述:
设有n=2k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表:
每个选手必须与其他n-1个选手各赛一次;
每个选手一天只能参赛一次;
循环赛在n-1天内结束。
请按此要求将比赛日程表设计成有n行和n-1列的一个表。在表中的第i行,第j列处填入第i个选手在第j天所遇到的选手。其中1≤i≤n,1≤j≤n-1。
-------------------------------------------------------------------------
解答:
这个算法被划分到了分治算法的例子,的确它包含分治算法的意思,但是如果从构建规则出发,而不是从分治思想出发,我怎么感觉想起来更不绕弯呢!
其实这个表的构建很容易。首先有个数组T,n行n列,第一列第一行填入数字1,初始就是这个样子的。
此时k=0,由它向下扩展,向右扩展,向右下扩展就变成了k=1的情况,即由一行一列变成二行而列,如何扩展呢?
向下:原始值(左上角)加1(k)向下搬
右上:把刚才填充上的左下的搬上去
右下:把原来的,左上的搬下去。
按照这个规律,当K=2的时候,应该是这个样子的
当K=3的时候,应该是这个样子的
把第一列去掉就是我们想要的8个运动员的比赛日程表。
想通了,代码就非常容易了。
设有n=2k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表:
每个选手必须与其他n-1个选手各赛一次;
每个选手一天只能参赛一次;
循环赛在n-1天内结束。
请按此要求将比赛日程表设计成有n行和n-1列的一个表。在表中的第i行,第j列处填入第i个选手在第j天所遇到的选手。其中1≤i≤n,1≤j≤n-1。
-------------------------------------------------------------------------
解答:
这个算法被划分到了分治算法的例子,的确它包含分治算法的意思,但是如果从构建规则出发,而不是从分治思想出发,我怎么感觉想起来更不绕弯呢!
其实这个表的构建很容易。首先有个数组T,n行n列,第一列第一行填入数字1,初始就是这个样子的。
1 | … |
… | … |
向下:原始值(左上角)加1(k)向下搬
右上:把刚才填充上的左下的搬上去
右下:把原来的,左上的搬下去。
1 | 2 | |
2 | 1 | |
1 | 2 | 3 | 4 | |
2 | 1 | 4 | 3 | |
3 | 4 | 1 | 2 | |
4 | 3 | 2 | 1 | |
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
2 | 1 | 4 | 3 | 6 | 5 | 8 | 7 |
3 | 4 | 1 | 2 | 7 | 8 | 6 | 6 |
4 | 3 | 2 | 1 | 8 | 7 | 5 | 5 |
5 | 6 | 7 | 8 | 1 | 2 | 3 | 4 |
6 | 5 | 8 | 7 | 2 | 1 | 4 | 3 |
7 | 8 | 5 | 6 | 3 | 4 | 1 | 2 |
8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
想通了,代码就非常容易了。
/// <summary> /// 生成比赛日程表 /// </summary> /// <param name="k">运动员数为2的n次方</param> public void GenerateTable(int n) { int N=(int)Math.Pow(2,n); int[,] T=new int[N,N]; T[0, 0] = 1; for (int k = 0; k < n; k++) { int end=(int)Math.Pow(2,k)-1; //左上小方块结束的行和列 int end2 = (int)Math.Pow(2,k+1) - 1; //本次填充结束的行和列 int baseNum = (int)Math.Pow(2,k); //左下填充 for (int i = end + 1; i <= end2; i++) { for (int j = 0; j <= end; j++) { T[i, j] = T[i - baseNum, j] + baseNum; } } //右上填充 for (int i = 0; i <= end; i++) { for (int j = end + 1; j <= end2; j++) { T[i, j] = T[i + baseNum, j - baseNum]; } } //右下填充 for (int i = end + 1; i <= end2; i++) { for (int j = end + 1; j <= end2; j++) { T[i,j]=T[i-baseNum,j-baseNum]; } } } //output StringBuilder sb = new StringBuilder(); for (int i = 0; i < N; i++) { for (int j = 1; j < N; j++) { sb.Append(T[i,j]+" "); } sb.Append("\n"); } Console.WriteLine(sb); Console.ReadKey(); }
相关文章推荐
- 循环赛日程表算法
- 算法练习-NOJ-1243-循环赛日程表
- 循环赛日程表(计算机算法设计与分析 --王晓东) 2.11
- 算法分析思维分析,以循环赛日程表为例
- 算法之循环赛日程表
- 循环赛日程表算法
- 关于循环赛日程表算法的研究
- JAVA代码—算法基础:循环赛日程表
- [算法之分治法应用] 循环赛日程表
- C++循环赛日程表算法
- 【算法-分治策略应用】循环赛日程表问题
- 循环赛日程表(用来说明算法导论上的题目!!)
- 算法分析与设计-04-循环赛日程表算法
- 循环赛日程表算法
- 2.11循环赛日程表
- “循环赛日程安排”问题的分而治之解决算法
- 循环赛日程表问题
- 分治法,循环赛日程表
- 分治法:循环赛日程表问题
- 紫书_第八章_高效算法设计_8.3.2——循环日程表问题