作业2
问题描述
编写程序实现循环赛日程表。设有n=2k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表:
(1)每个选手必须与其它n-1个选手各赛一次
(2)每个选手一天只能赛一场
(3)循环赛进行n-1天
问题思路
假设n位选手被顺序编号为1、2、…、n(2^k)。可将比赛日程表设计成一个n行n-1列的二维数组,其中第i+1行、第j+1列表示和第i个选手在第j天比赛的选手号。观察可知,数组均分四块后,其左上角等于右下角,左下角等于右上角。只要求出左上角和左下角的解,就能得出其余部分的解。
故采用分治法,将一个难以直接解决的大问题划分成一些规模较小的相同问题,便于各个击破。在此基础上,我写了3种算法。
(1)算法1:改写课件代码,采取自底向上的迭代。
(2)算法2:算法1的改写,采取自顶向下的递归。
(3)算法3:算法2的改写,仍采用自顶向下递归。
算法1
伪代码描述
1.输入k,总数为2k,a[0][0]=1,t=1
2.循环直到k为0
2.1 for i=0 to i=t //左上角的宽度为t
for j=0 to j=t
a[i+t][j+t]=a[i][j]; //填充右下角
a[i+t][j]=a[i][j]+t; //填充右上角
a[i][j+t]=a[i][j]+t; //填充左下角
2.2 t=t*2 //新的左上角产生,迭代填充
2.3 k--
3.输出a
算法时间复杂度分析
T(k)表示2^k个选手循环赛问题的求解时间,T(k)满足如下递推式:
T(k)=1 k=1
T(k)=4T(k-1) k>1
解此递推式可得T(k)=O(4^k)。
C++描述
#include<iostream>
#include<Windows.h>
#include<iomanip>
using namespace std;
void Plan(int a[][256],int k)
{
a[0][0]=1;
int i,j,t=1;
while(k--) //k为迭代次数
{
for(i=0;i<t;i++) //t表示左上角的a[0][0]到a[t-1][t-1]填充完毕
{
for(j=0;j<t;j++) //左上角的宽度为t
{
a[i+t][j+t]=a[i][j]; //填充右下角
a[i+t][j]=a[i][j]+t; //填充右上角
a[i][j+t]=a[i][j]+t; //填充左下角
}
}
t=t*2; //新的左上角产生,接着填充
}
cout<<"算法1"<<endl;
for(i=0;i<t;i++) //t为总人数,输出数组a
{
for(j=0;j<t;j++)
{
cout<<setiosflags(ios::left)<<setw(3)<<a[i][j];
}
cout<<endl;
}
}
int main