您的位置:首页 > 其它

算法-分治法实例:循环赛日程安排问题

2015-10-12 21:09 218 查看

一、问题描述

设有 n(2^k)位选手参加网球循环赛,循环赛一共需要进行 n-1天,每位选手需要和其他的 n-1 位选手各比赛一场,不轮空。试着安排这个比赛的安排日程。

二、问题分析

本问题可以利用分治法来进行求解,设 n位选手被顺序标号为1,2,3,……,n。比赛的日程是一个n 行和 n - 1 列的表,第 i 行第j 列就是第i 号选手的第 j 天的比赛对手。

想要用分治法来设计日程表,就是从其中一半的选手的比赛日程来导出所有选手的比赛日程,从众所周知的只有两个选手的比赛日程出发,反复推理和扩充整个比赛日程,直到第 n 位选手的比赛日程安排好了为止。

接下来是程序:

#include <stdio.h>
#include <math.h>
#include <malloc/malloc.h>

//采用分治法来进行网球循环赛的基本赛制的安排。
int ** GameTable(int k){
//首先分配一个矩阵 A 用来存放将要相互比赛的结果,第一列为所有选手的编号,每一行就是该选手和其他选手的比赛次序,且不使用下标为0的元素。
int ** A = (int**)malloc(sizeof(int*)*((int)pow(2, k))+1);
int i,j,t;
for (i = 1;i <= (int)pow(2, k);i++) {
A[i] = (int*)malloc(sizeof(int)*((int)pow(2, k)+1));
}
//初始化基本元素并开始利用分治法来对时程表进行扩充
int n = 2;//递增用于扩充安排表的变量
A[1][1] = 1;
A[1][2] = 2;
A[2][1] = 2;
A[2][2] = 1;
for (t = 1; t < k; t++) {
//用分治法来填充日程表
int temp = n;
n *= 2;
//扩充左下角
for (i = temp + 1; i <= n; i++) {
for (j = 1; j <= temp; j++) {
A[i][j] = A[i-temp][j] + temp;
}
}
//扩充右上角
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];
}
}
}
return A;
}

//初始化输入并且打印输出结果
void InputAndOut(){
int CounterOfPeopleInTennis = 0;
printf("请输入这一届参加比赛的选手人数有(必须为二的幂不然无法安排比赛):");
scanf("%d",&CounterOfPeopleInTennis);
if (CounterOfPeopleInTennis % 2 != 0) {
printf("输入错误!请准备重新输入:\n");
InputAndOut();
}
else{
int k = 0;
while (CounterOfPeopleInTennis != 1) {
k++;
CounterOfPeopleInTennis /= 2;
}
int ** Tennis_People;
Tennis_People = GameTable(k);
printf("本次循环网球赛的对决安排结果如下:\n");
for (int i = 1; i <= (int)pow(2, k); i++) {
for (int j = 1; j <= (int)pow(2, k); j++) {
printf("%3d",Tennis_People[i][j]);
}
printf("\n");
}
}
}

int main(int argc, const char * argv[]) {
InputAndOut();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: