问题描述
设有 n = 2的k次方 个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表:
(1)每个选手必须与其他n-1个选手各自赛一次。
(2)每个选手一天只能赛一次。
(3)循环赛一共进行n-1天。
算法设计
按分治策略,我们可以将所有的选手分为两半,n个选手的比赛日程表可以通过n/2个选手设计的比赛日程表来决定。
递归地用这种一分为二的策略对选手进行分割,直到只剩下两个选手时,比赛日程表的制定就变得很简单。
这时只要让这两个选手进行比赛就可以了。
#include "stdafx.h"
#include<iostream>
using namespace std;
#include <stdio.h>
#include <string.h>
int a[1000][1000];
void output(int k);
int Table(int k)
{
int i, j;
int n = 1;
for (i = 1; i <= k; i++)
n *= 2;
for (i = 1; i <= n; i++)
a[1][i] = i;
int m = 1;
for (int s = 1; s <= k; s++)
{
n /= 2;//n是需要复制几次
for (int t = 1; t <= n; t++)
{
for (i = m + 1; i <= 2 * m; i++)//行
{
for (j = m + 1; j <= 2 * m; j++) // 列
{
a[i][j + (t - 1)*m * 2] = a[i - m][j + (t - 1)*m * 2 - m];
a[i][j + (t - 1)*m * 2 - m] = a[i - m][j + (t - 1)*m * 2];
}//(t - 1)*m * 2 m*2->1 2 3 4
} //m=1时 // 2 1 4 3 (t - 1)*m * 2便能到4的位置
output(k);
}
m *= 2;//行列的多少
}
output(k);
return 0;
}
void output(int k)
{
int n = 1, i, j;
for (i = 1; i <= k; i++)
n *= 2;
for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
printf("%d ", a[i][j]);
putchar('\n');
}
}
int main()
{
int i, j, k;
cin >> k;
Table(k);
system("pause");
return 0;
}