没有合适的资源?快使用搜索试试~ 我知道了~
单循环赛中选手胜负序列求解问题(报告)
需积分: 46 9 下载量 124 浏览量
2009-05-17
23:56:36
上传
评论 1
收藏 114KB DOC 举报
温馨提示
试读
16页
有n个选手 P 1 ,P 2 ,P 3 ,… ,P n 参加了的单循环赛,每对选手之间非胜即负。现要求求出一个选手序列 P 1 ' ,P 2 ' ,P 3 ' ,… ,P n ', 使其满足 P i ' 胜 P i+ 1 ' (i=1,… ,n-1) 。
资源推荐
资源详情
资源评论
XX 学院
计算机科学与技术系
课程设计报告
2008 ~2009 学年第 2 学期
课 程 数据结构与算法
课 程 设 计 名 称 单循环赛中选手胜负序列求解问题
学 生 姓 名
学 号
专 业 班 级 07 计算机科学与技术系
指 导 教 师
2009 年 2 月
题目:单循环赛中选手胜负序列求解问题
一、 问题分析和任务定义
单循环赛:
单循环赛,是所有参加比赛的队均能相遇一次,最后按各队在全部比赛中的积分、得
失分率排列名次。如果参赛球队不多,而且时间和场地都有保证,通常都采用这种竞赛方
法。 单循环比赛轮次的计算
本题可有两种不同的理解,一个是按比赛的积分排名产生胜负序列,第二个是按比赛
过程中各个选手间的胜负关系产生胜负序列,下面具体分析:
(1) 按比赛中积分排名产生胜负序列:
比赛可规定各个选手之间均遭遇且只遭遇一次,比赛时胜方得 1 分,负方不得分,在
比赛结束时按积分排名进行排序,由此产生胜负序列关系。
(2) 按比赛过程中各个选手间的胜负关系产生胜负序列:
该种方法是以过程中的胜负为标准从而产生胜负序列,当然,这种胜负序列很大的可
能性是不唯一的,本程序按课程设计任务书的要求,仅求出其中的一个胜负序列关系。
二、 数据结构的选择和概要设计
(1)对于第一种情况,本实验选用的数据结构是类。将选手的编号、积分、以及胜负处
理等等封装在类中。胜负序列的求解转化为了对所有选手的积分的排序问题。
(2)对于第二种情况,本实验采用的数据结构是有向图,每个选手视为一个点,每条
边视为选手之间的胜负关系,箭头指向的一方为失败方。所以胜负序列的求解就转化为了
图的深度遍历问题。为了便于深度遍历有向图,采用的存储结构为图的临街矩阵存储。
三、 详细设计和编码
(1)就第一种情况而言,较为简单,设计一个选手类Player,私有成员包括分数scor
e和选手编号num。公有成员包括构造函数Player(),设置编号void setnum(int num1),
获胜处理函数void win(),失败处理函数void fail(),返回编号函数int getnum(),返
回积分函数int getscore()。类的定义如下:
class player//选手类
{
private:
int score;//积分
int num;//参赛编号
public:
player()
{}
void setnum(int num1)//设置编号
{
num = num1;
score = 0;
}
void win()//胜利
{
score ++;
}
void fail()//失败
{
score --;
}
int getscore()//获取分数
{
return score;
}
int getnum()//获取编号
{
return num;
}
};
这些代码定义为头文件 score.h
在程序的初始化时根据输入的选手数量n,动态申请一个选手类的数组Player[n]。依次
输入第一个选手和后面的n-1个选手的胜负关系,第二个选手和后面n-2个选手的胜负关系
……第n-1个选手和第n个选手的胜负关系。W(w)表示胜利,F(f)表示失败。
在选手的胜负关系输入完毕后通过getscore()返回各个选手的积分对各个选手的积
分进行排序,从而得到选手的胜负序列关系。
(2)就第二种情况而言,较为复杂,使用的图,即将比赛过程中的各个选手间的胜
负关系转化为一个有向图且是连同的完全有向图。
模型表示 :由于仅涉及到 n 个选手,并且这些选手之间的关系仅是胜负关系,因此可
用图来表示,用顶点表示选手, 用弧表示选手之间的胜负关系:当且仅当 P i 胜 P j 时,
有从顶点 i 到 j 的一条弧。
在这种表示下,本题问题变成了如下的问题:
在有向图中求解出一条包含所有顶点的简单路径的问题。
下图所示为一个有 8 个选手的问题的一个示例。其中的一个解为 1,2,3,4,8,6,5,7 。
算法设计 :设计本题算法的构思如下:
为搜索出符合条件的简单路径,需按深度优先搜索方式进行遍历。因此求解算法应 是
深度遍历算法的变形形式 ,也应是递归形式的算法。
由于要求遍历序列中的各结点按次序构成一条简单路径,因此算法与深度遍历算法有
明显的不同:并非任意选择的起点和访问次序都能得到解。而这些又是事先难以确定的。
这就要求在求解过程中进行试探: 试探起点以及访问次序 。
既然要在求解过程中进行试探,则 需要记录试探的中间状态 :某顶点是否在当前试
探的路径中,已经试探的各顶点的次序,当前正在试探的顶点等。将所用到的变量及有关
参数设置如下:
设置 MAX_POINT_NUM 100 为最大选手数量。路径结构 WAY,包含路径上选手在
序列数组 中的小标 k 和选手序列 way[MAX_POINT_NUM] ,都 是整型 。 设置结构 体
Graph 为图的 存 储 结构,包 含选 手 的 人数 n 和存储矩 阵 edges[MAX_POINT_NUM]
[MAX_POINT_NUM],为邻接存储矩阵,即本程序采用临街矩阵作为图的存储结构。
设图为 g ,设当前试探路径中最后的顶点号为 i , i 在试探路径中的序号为 k,用整
型数组 visited[n] 表示各顶点是否在当前试探的路径中(初值为全 0 ),用路径 w 中的
way[MAX_POINT_NUM] 存储当前路径中的各顶点(在前 k 个元素中,事实上应是栈)。
既然是试探型求解,则需对当前顶点 i 的每个邻接点 ( 不妨用 j 表示 ) 进行试探,试探
由 i 经 j 往下是否可以得到解。每个 i 都可能有成功(指现在可以将该顶点放在路径上,
这包括暂时的和最终的)与失败(指此路不通)两种情况,对此应分别作不同的处理:
a. 若试探成功,则应将 j 放入路径中,并置相应的状态值。然后再由 j 往下求解。
b. 若不成功,则应恢复 j 的有关信息,以使 j 在试探其它路径时成为可选顶点。
为了能求出解以及所有可能的解,需要作如下两方面的工作:
a. 选择起点:应以每个顶点为起点进行搜索。
b. 搜索路径:在从 i 往下搜索时,应依次选择 i 的所有不在当前试探路径中的邻接点
往下搜索。
为此,需要有这方面的保证:应在试探某顶点 j 后并在换下一个试探顶点前恢复 j 的
有关状态,以使其仍为可选择的顶点。
由上述讨论得本算法的基本思想:
a. 若 k=n-1 ,则说明已经求得一解,因此可输出结果,并结束本次调用。
b. 若 k<n-1 ,则依次选择 i 的所有不在当前试探路径中的邻接点 j 往下搜索,这包
括以下的操作:
试探:将 j 放到 way[MAX_POINT_NUM] 中,并置 visited[j] 为 1 ,然后以 j 为起
点往下搜索。
恢复:将 j 恢复为不在当前路径中,以使其在试探其它路径时可用。
有关算法中的变量设置:可将上述讨论中所提及的变量 k 、 i 作为参数(仅提供值而
不返回值),将 g 作为地址传送型参数(虽然不会改变其值,但这种形式更节省时间和空
间),将数组 way 和 visited 作为全程变量,以便各调用层能共享,并节省时间、空间,
同时使程序更清晰。
算法描述:
程 序 开 始 要 求 输 入 选 手 的 数 量 ( 即 图 中 点 的 个 数 ) 。 并 初 始 化
way[MAX_POINT_NUM] 全 为 -1 , visited[j] 为 1 , 邻 接 矩 阵
edges[MAX_POINT_NUM][MAX_POINT_NUM]全为 0。提示依次输入第一个选手和后
面的 n-1 个选手的胜负关系,第二个选手和后面 n-2 个选手的胜负关系……第 n-1 个选手和
第 n 个选手的胜负关系。W(w)表示胜利,F(f)表示失败。
初始化完成后尝试以不同的选手为起点进行搜索(从第 1 个到第 n 个)。每次选择新的起
点时对以上各个数组个数据从新初始化。
Graph *Creat_Graph(int n),为图的建立函数,根据选手的人数设置进行必要的初
始化并且根据用户输入的胜负关系置相应的状态。
剩余15页未读,继续阅读
资源评论
xiaobia
- 粉丝: 1
- 资源: 17
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功