循环赛日程表

问题描述

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

(1)每个选手必须与其他n-1个选手各赛一次;
(2)每个选手一天只能参赛一次;
(3)循环赛在n-1天内结束。
请按此要求将比赛日程表设计成有n行和n-1列的一个表。在表中的第i行,第j列处填入第i个选手在第j天所遇到的选手。其中1≤i≤n,1≤j≤n-1。

思路

分治,可以用递归或者迭代实现
迭代:

#include<iostream>
#include<cmath>
using namespace std;
int a[100][100];
void gametable(int k)
{
	int n,tmp,i,j,t;
	n=2;//最小的表,相当于递归出口
	a[1][1]=1;a[1][2]=2;
	a[2][1]=2;a[2][2]=1;
	for(t=1;t<k;t++)//迭代填表,依次处理2^2...2^k个选手的比赛日程
	{
		tmp=n;
		n*=2;
		for(i=tmp+1;i<=n;i++)
			for(j=1;j<=tmp;j++)
				a[i][j]=a[i-tmp][j]+tmp;//左下角与左上角相对应
		for(i=1;i<=tmp;i++)//左下角抄到右上角
			for(j=tmp+1;j<=n;j++)
				a[i][j]=a[i+tmp][(j+tmp)%n];
		for(i=tmp+1;i<=n;i++)//左上角抄到右下角
			for(j=tmp+1;j<=n;j++)
				a[i][j]=a[i-tmp][j-tmp];
	}
	cout<<"参赛人数为:"<<n<<endl;
	cout<<"(第i行第j列表示和第i个选手在第j天比赛的选手序号)"<<endl;
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=n;j++)
			cout<<a[i][j]<<' ';
		cout<<endl;
	}
}
int main()
{
	int k;
	cout<<"比赛选手个数为n(n=2^k),请输入参数K(K>0):"<<endl;
	while(cin>>k&&k)
	{
		gametable(k);
		cout<<endl;
	}
	return 0;
}

递归:

#include<iostream>
using namespace std;
int n,a[100][100],len;

void UpRightCopy(int n)
{
	for(int i=1;i<=n;i++)
		for(int j=n+1;j<=2*n;j++)
			a[i][j]=a[i][j-n]+n;
}

void DownRightCopy(int n)
{
	for(int i=n+1;i<=2*n;i++)
		for(int j=n+1;j<=2*n;j++)
			a[i][j]=a[i-n][j-n];
}

void LeftDownCopy(int n)
{
	for(int i=n+1;i<=2*n;i++)
		for(int j=1;j<=n;j++)
			a[i][j]=a[i-n][j]+n;
}

void turn(int n)
{
	if(n==1)
		a[1][1]=1;
	else
	{
		turn(n/2);
		DownRightCopy(n/2);
		UpRightCopy(n/2);
		LeftDownCopy(n/2);
	}
}

int main()
{
	while(cin>>n)
	{
		len=1;
		for(int i=1;i<=n;i++)
			len*=2;
		n=len;
		turn(n);
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
				cout<<a[i][j]<<' ';
			cout<<endl;
		}
	}
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值