循环赛日程表Java代码实现及详细思路

问题描述

设有 n = 2 k n=2^k n=2k个运动员要进行羽毛球循环赛,现要设计一个满足以下要求的比赛日程表:

  1. 每个选手必须与其它n-1个选手各赛一次;
  2. 每个选手一天只能比赛一次;
  3. 循环赛一共需要进行n-1天。由于n=2k,显然n为偶数。

代码

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	static int[][] schedule;
	public static void process(int k, int[][] schedule) {
//		计算运动员总人数
		int n = 1;
		for (int i = 0; i < k; i++) n*=2;
//		分配空间,零行零列空缺
		schedule = new int[n+1][n+1];
//		顺次列出运动员编号schedule[1][1]~schedule[1][n]
		for (int i = 1; i <= n; i++) schedule[1][i] = i;
		int m = 1;
		for (int s = 1; s <= k; s++) {
			n/=2;
			for (int t = 1; t <= n; t++) {
				for (int i = m + 1; i <= 2 * m; i++) {
					for (int j = m + 1; j <= 2 * m; j++) {//
//						根据这个日程表对应规律可知,行和列都差了m
						schedule[i][j+(t-1)*m*2]=schedule[i-m][j+(t-1)*m*2-m];
						schedule[i][j+(t-1)*m*2-m]=schedule[i-m][j+(t-1)*m*2];
					}
				}
			}
			m*=2;
		}
		for (int[] item : schedule)
			System.out.println(Arrays.toString(item));
		System.out.println();
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//输入k,运动员的人数为2^k
		int k;
		Scanner scanner = new Scanner(System.in);
		k = scanner.nextInt();
		process(k,schedule);
		
	}

}

结果展示

输入为3,即运动员数量为8个
在这里插入图片描述

代码思路

当运动员人数为8时,我们可以很容易排出一张日程表,满足题目的要求。

在这里插入图片描述

观察后发现日程表第一行即运动员编号的顺序排列,然后我们发现第二行与第一行非常大的关系,即交叉复制的关系。
在这里插入图片描述

而第三四行似乎也与前两行有交叉复制的关系,

在这里插入图片描述

这样看来,我们只要不断地交叉复制前面地数据即可,那么在代码中如何体现这个思路呢

我把代码中最重要的部分重新拿出来了,我们一起看一下程序是如何运行的。

int m = 1;
		for (int s = 1; s <= k; s++) {//第一个循环
			n/=2;
			for (int t = 1; t <= n; t++) {//第二个循环
				for (int i = m + 1; i <= 2 * m; i++) {//第三个循环
					for (int j = m + 1; j <= 2 * m; j++) {//第四个循环
//						根据这个日程表对应规律可知,行和列都差了m
						schedule[i][j+(t-1)*m*2]=schedule[i-m][j+(t-1)*m*2-m];
						schedule[i][j+(t-1)*m*2-m]=schedule[i-m][j+(t-1)*m*2];
					}
				}
			}
			m*=2;
		}

由于这个规模是以除2的速率缩小的的,即要解决一个8人的日程表,第一次完成第二行,第二次完成三四行,第三次就完成了日程表,因此我们的第一个循环用k约束复制的轮数。需要记住的是,第s次循环我们要完成 2 i − 1 2^{i-1} 2i1行(1行,2行,4行,…)。

而这里的n又有什么作用呢?

我们观察到,第一次需要交叉复制4次,第二次2次,第三次1次,不明白的可以参看上面的图片,因此我们用n来约束交叉复制的次数。这样我们就知道了第三四个循环其实是完成一次交叉复制。由变量i来控制行,j来控制列。

第二行交叉复制的次序

在这里插入图片描述

第三四行交叉复制的次序
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值