分治法实现循环赛日程安排问题

题目:
设有n=2^k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表:(1)每个选手必须与其他n-1个选手各赛一次; (2)每个选手一天只能参赛一次; (3)循环赛在n-1天内结束。 请按此要求将比赛日程表设计成有n行和n-1列的一个表,最后在完成比赛结果的输入和最终成绩的输出。在表中的第i行,第j列处填入第i个选手在第j天所遇到的选手。其中1≤i≤n,1≤j≤n-1。8个选手的比赛日程表如下图:分治法实现循环赛日程安排问题
!!! 我这个对原题目有一些改动,自己加了成绩的输入和结果的输出
源代码:
#include<stdio.h>
#include<math.h> //pow函数
void Table(int k,int a[100][100]){//日程表函数
int t,n=2,i,j;
a[1][1]=1,a[1][2]=2;//初始化最小表格
a[2][1]=2,a[2][2]=1;
for(t=1;t<k;t++){//循环 k 次后得到的次数为 2 的 k+1 个格子 ,因此只需要循环 k-1 次 。
int temp=n;
n=n2;
for(i=temp+1;i<=n;i++)//根据左上写左下
for(j=1;j<=temp;j++)
a[i][j]=a[i-temp][j]+temp;//数之间的规律:与上一块与之对应的地方多 2
t
for(i=1;i<=temp;i++)//根据左下写右上
for(j=temp+1;j<=n;j++)
a[i][j]=a[i][j-temp]+temp;//左上写右上
for(i=temp+1;i<=n;i++)//根据左上写右下
for(j=temp+1;j<=n;j++)
a[i][j]=a[i-temp][j-temp]; //数之间的规律:所形成的以 temp+1 为边长长的的正方形的对角
}
}
void Print(int k,int a[100][100]){//输出函数
int n=pow(2,k),i,j,sum=0;
for(i=1;i<=n;i++){
for(j=1;j<=n;j++)
printf(" %d “,a[i][j]);
printf(”\n\n");
}
}
int Score(int len,int a[100][100]){//统计分数函数
int i,j,k;
int sum[100]={0};
for(i=1;i<=len;i++){//分数数据的规律:以发起人的分数总和加上 0-作为对手的分数
for(j=i+1;j<=len;j++)
sum[i]+=a[i][j];
for(k=1;k<i;k++)
sum[i]-=a[k][i];
}
printf("\n\n分数统计如下:\n\n");
for(i=1;i<=len;i++)
printf(“第%d名选手总成绩为:%d\n”,i,sum[i]);
printf("\n\n选手成绩排名从高到低为:\n\n");
Sort(len,sum);
}
int Sort(int len,int a[100]){//冒泡排序法对数组进行排序并输出数组下标 即对分数排名输出选手号
int flag[100],i,j,temp,k;//建立一个新的数组,将下标赋予每个数组值,目的是记录将要排序的数组的下标
for(i=0;i<100;i++)
flag[i]=i;
for(i=0;i<=len;i++)
for(j=1,k=0;j<len;j++,k++)
if(a[j]<a[j+1]){
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
temp=flag[k];
flag[k]=flag[k+1];
flag[k+1]=temp;
}
for(i=0;i<len;i++)
printf(“第%d名选手\n”,flag[i]+1);//因为sum数组遍历是从1开始,所以这里输出flag[i]+1
printf("\n\n恭喜第%d名选手夺冠!\n",flag[0]+1);
printf(“恭喜第%d名选手获得亚军!\n”,flag[1]+1);
printf(“恭喜第%d名选手获得季军!\n”,flag[2]+1);
}
int main(){
int i,j,k,calendar[100][100];
int statistics[100][100]={0};
printf(“请输入整数k的值:”);
scanf("%d",&k);
int n=pow(2,k);
printf("\n日程表安排如下:\n\n");
Table(k,calendar);
Print(k,calendar);
printf("\n\n请输入比赛结果:\n\n");
int q=n-1;//胜出输入1,失败输入-1,若平局输入0
for (i=1;i<n;i++){
printf(“以第%d名选手%为发起人的%d个比赛结果:”,i,q–);
for(j=i+1;j<=n;j++)
scanf("%d",&statistics[i][j]);
}
Score(n,statistics);
return 0 ;
}
成绩录入和结果输出部分思路:
分治法实现循环赛日程安排问题

因为每个选手要不重复的与其他选手比赛一场,规定赢得比赛记1分,平局记0分,输掉比赛记-1分。如表格所示,将不带括号的数成为发起者,括号内的数称为被挑战者,以第三号选手为例,不难发现第第二列全部都是挑战三号选手,在第二列中三号选手的得分为 -1(3)- 2(3),而第三行都是三号选手作为发起者,所以第三行中三号选手的得分为 3(4)+3(5)+…+3 ( 8 ) ,最后第三行加第二列便为三号选手的总分。

ending~~~
关于成绩输入部分是我个人想法
我也不晓得对不对
我觉得是对的
hhhh
我只是一个平平无奇小菜鸡~
一起进步吖~