年级 04 计算机科学与技术系 (2)班 姓名 余志中 学号 0410101080
田径运动会赛程安排
题目:在一个田径运动会上,已知有 m 个选手参加比赛,运动项目共有 n 个,这包括若干个
诸如 100m 之类的以个人形式参加的单项和 4×100m 之类的多人参加的集体项目。另外,每
位选手最多可参加 3 个单项,集体项目则不限制。为使选手能正常比赛,需要对赛程作合理
安排。请构造出有关模型和数据结构,设计出合理安排赛程的算法和程序,以使每位选手都
能正常地参加比赛,并要求比赛时间尽可能短。
一 问题分析和任务定义
问题分析:首先怎样考虑选手报名情况,我们可以规定有 m 个选手报名参加了这次田径运动
会项目,并给他们从 1 到 m 编号代替他们。由于实际情况我们规定有 n 个田径比赛项目,分
别为个人形式参加的单项项目为 100 米等。多人参加的集体项目有 4*100 米等项目。由于题
目规定每位选手最多可参加 3 个单项,集体项目不限制。所以我们假设每人参加的项目就用
1 表示,没参加用 0 表示。可以用列表来表示相关模型,例如模型如下:
项
目选
手
100
1500
铅球
跳高
跳远
4*100
8*100
1
2
3
4
5
0
1
1
0
0
0
0
1
0
0
1
0
0
1
0
0
1
1
0
1
0
0
0
1
1
1
1
0
0
0
1
0
1
0
0
由于选手参加的条件不能超过 3 个单人项目,所以在参加之前先判断是否符合条件,若不符
合则对选手排除。
任务定义: 比赛赛程要求时间尽可能的短,所以需要两方面的条件,如下:
(一) 项目之间由于比赛场地的限制,不能同时进行。其中能同时进行的要判断哪些能同
时进行,而田赛场地不同所以都能同时进行。
(二) 在条件(一)的情况下,同一个选手选择了相同项目不能同时进行.
功能:
(一) 编号 1 到 100 个选手参加 7 个项目分别是 100 米, 1500 米,铅球,跳高,跳远单
人项目和 4*100 米,8*100 米等多人项目。
(二) 每个项目参加的人数,而且要判断多人比赛项目报名参加的人数,是否能正确分组。
1
年级 04 计算机科学与技术系 (2)班 姓名 余志中 学号 0410101080
(三) 根据报名表合理安排赛程
输入形式:输入各个项目的报名表,以及跑道的规则(整形)
输出形式:根据报名表输出赛程的安排,其中包括项目的先后顺序,以及项目的参加人数。
(整形)
算法的功能:在有限的时间内尽可能短的合理的安排赛程
测试所需的数据和类型:参加人数 100 人,每个项目所报的人数。
二 概要设计和数据结构的选择
数据结构:由上表可示,可用矩阵来存储表格中的数据,可设如下:
矩阵 A[m][n]存储各个结点,各结点包含两个成员 运动项目和整形变量 1 或 0,1 表示 n
参加了 m 项目,0 表没有参加。
主程序的简体流程图:
定义数组并赋值
判断每人参
加单项是否
符合条件
各项参加的人数
由跑道规则判断各
项能否同时进行
各项项目参加的人没有重复
能同时进行的项目
排出田径运动会的赛程
三 详细设计和编码
先用结构体存储各个结点的信息,每个选手参加单人项目和多人项目用 1 表示不参加用
零表示各项目的信息,结构体五存储表示项目能同时进行的用 tag 表示。然后存储各个项目
参加的人数和场地的信息,以及每轮比赛的所需时间。再用一个结构体存储每个人的信息包
括每人参加的单项和多项以及总的项目数;
2
年级 04 计算机科学与技术系 (2)班 姓名 余志中 学号 0410101080
typedef struct
{
int n;//n=1 为单项,n>1 时为集体项目
int data;
int T;//参加标志符
}N1;
typedef struct
{
N1 tod[maxsize1];
int sum1;//单项比赛项目数
int sum2;//集体比赛项目数
int sum;//比赛总项目数
}N2;
typedef struct
{
N2 pre[maxsize2];//存放每位选手参加项目信息
int H;//选手个数
}N3;
N3 list1;
typedef struct
{
int M1;//项目 M1
int M2;//项目 M2
int tg;//M1,M2 可以同时进行标志
}N4;
typedef struct
{
N4 a[maxsize3];//数组每个元素存放所有可以同时进行的两个项目
int gb;
}N5;
3
年级 04 计算机科学与技术系 (2)班 姓名 余志中 学号 0410101080
N5 list2;
typedef struct
{
int pop;//比赛项目
char cd;//比赛项目举行场地
}N6;
typedef struct
{
N6 tod[maxsize1];
}N7;
N7 list3;
流程一 先设一个子函数求出每个人参加各个项目的总数;
int bag1(N3 *list,int i)//第 i 个人参加单项总个数
{
}
int bag1=0;
int j;
for(j=1;j<=list->pre[i].sum1;j++)//统计单项
if(list->pre[i].tod[j].T==1)//第 i 个人参加第 j 个单项
bag1++;
return bag1;
流程二 求出每个项目参加的总人数
int bag2(N3 *list,int i)//第 i 个项目参加人数
{
int bag2=0;
int j;
for(j=1;j<=list->H;j++)//第 j 个选手
if(list->pre[j].tod[i].T==1)
bag2++;
return bag2;
4
年级 04 计算机科学与技术系 (2)班 姓名 余志中 学号 0410101080
}
流程三 判断每个人所报的项目是否符合标准,即每人不得参加超过 3 个单人项目,如过超
过则把此人删除
void del(N3 *list,int i)//取消第 i 个选手参赛资格
{
}
int j;
for(j=i;j<=list->H;j++)//i 以后的选手依次前移
list->pre[j]=list->pre[j+1];
list->H--;//选手个数减少一个
流程四 判断不同场地上能不能同时进行的项目,若不能则返回,若能则存储在 list2 中
N5 *moon1(N7 *list3,N5 *list2)//不同场地上进行的比赛可以同时进行
int i,j,k=1;//i,j 控制循环 k 是数组下标
//且放到 list2 中
list2->gb=0;
for(i=1;i<=6;i++)
{
for(j=i+1;j<=7;j++)
{
}
list2->a[k].M1=list3->tod[i].pop;list2->a[k].M2=list3->tod[j].pop;
if(list3->tod[i].cd!=list3->tod[j+1].cd)//举行场地不同可同时进行
list2->a[k].tg=1;
else list2->a[k].tg=0;//不能同时进行
k++;//数组下标
list2->gb++;
}
return list2;
{
}
流程五 在流程四的条件下能同时进行比赛的项目再考虑同一个选手同时参加了此项目组。
5
年级 04 计算机科学与技术系 (2)班 姓名 余志中 学号 0410101080
N5 *moon2(N3 *list,N5 *list2)//在存放可同时进行比赛数组中删除某选手交叉的项目
{
int i,j,t,k=1;
for(i=1;i<=list->H;i++)//第 i 个人参加的交叉项目
for(j=1;jpre[i].sum;j++)//从第 i 个人参加的第 j 个项目开始
{
if(list->pre[i].tod[j].data==list2->a[k].M1&&list->pre[i].tod[j].T==1)
for(t=j+1;t<=list->pre[i].sum;t++)
if(list->pre[i].tod[t].data==list2->a[k].M2&&list->pre[i].tod[j].T==1)
{
}
list2->a[k].tg=0;
k++;
return list2;
}
}
四 上机调试
源程序的输入和代码的调试:输入:输入任意键进入程序;输出:由于项目给定和参加的人
数是随机产生所以这个程序输出结果任意。
调试过程中遇到的主要问题:
1) 表只有先初始化后才能将其地址赋给一指针变量
2)子函数中形式参数不能由实参直接传给应该将其地址传给形参
3)两比赛能否同时进行须两两比较即第 i 项依次与其以后的各项比较,控制循环
for(i=1;i<=6;i++)
for (j=i+1;j<=7;j++)即 i 只须从 1 到 6, j 则从 i+1 到 7
设计实现的回顾讨论和分析:这个程序设计题如果独立完成比较困难,而且一开始对题目认
识不够,走了不少弯路,而且要了解田径运动会所有项目和各个项目举行的场地,需要很多
的课外知识。但这个程序设计起来比较困难,由于参加的项目多样化和参加的人数比较多,
6
年级 04 计算机科学与技术系 (2)班 姓名 余志中 学号 0410101080
又要考虑每个人只能参加 3 个单项。感觉表示起来比较难以下手,所以需要非常细心,如果
有半点粗心,就回导致程序难以运行。
在一些资料和网上很难找到类似的程序,没有正确的提示和参考,由于自己的能力有限,C
语言和数据结构课程学习的不太好,导致这个程序做的不好,以后会好好学习,认真做好该
做的事。
改进设想:由于这个程序所需的变量很多,参加的项目和参加的人数都已在主程序中已经赋
值,而报名表中的选手信息则有随机函数产生,所以这个函数并没有什么实用价值。
(1) 如果在函数中设置一个文件调用此文件中的信息,即文件中存储各个项目的信息和
参加的选手信息;然后,根据这个文件排出赛程先后顺序的安排。则会达到更好的
效果,若文件中存储更多的信息,则这个程序可以运用到很多方面。
(2) 这个程序中没有考虑到项目的时间,即若给出每个项目每轮比赛的时间再求出总的
时间,可知总个赛程大约需要多长时间来合理安排赛程。
时间和空间分析:时间复杂度:O(n³),空间复杂度:O(1)。
经验和体会:编程设计能够比较好的掌握所学的东西,而且需要比较系统的运用各中算法和
C 语言知识,而且需要全面的掌握知识,如果有一点掌握不牢,就会出现断程,使编程难以
进行下去。所以以后需要好好学习专业知识,不遗露半点知识,也要充分吸收和掌握课外知
识。
五 用户使用说明
这个程序可以先按任意键进入程序运行,调用子函数随机产生选手信息,然后根据这些信息
调用函数删除不符合条件的选手,再调用函数随机产生的选手参加每个项目参加的人数。并
排出每个项目安排赛程。
六 测试结果
7
年级 04 计算机科学与技术系 (2)班 姓名 余志中 学号 0410101080
七 附录
#include"stdio.h"
#include"stdlib.h"
#define maxsize1 15//比赛项目个数最大值
#define maxsize2 120//选手个数最大值
#define maxsize3 30//存放可同时进行项目数组
typedef struct
{
int n;//n=1 为单项,n>1 时为集体项目
int data;
int T;//参加标志符
}N1;
typedef struct
{
N1 tod[maxsize1];
int sum1;//单项比赛项目数
int sum2;//集体比赛项目数
8