分治法循环赛实验报告

实验一分治法
一、实验内容:
求解赛程问题
二、实验目的:
按照给出的实验算法的思路与步骤,编写程序源代码,验证该试验。
通过该实验,理解并掌握分治法的算法设计思想。
三、算法思想设计:
假设n位选手顺序编号为1,2,3…n,比赛的日程表是一个n行n-1列的表格。i行j列的表格内容是第i号选手在第j天的比赛对手。
根据分而治之的原则,可从其中以半选手的比赛日程,导出全体n位选手的的日程,最终细分到只有两位选手的比赛日程出发。
四、算法描述:
这个求解过程是自底向上的迭代过程,其中左上角和左下角分别为选手1至选手4以及选手5至选手8前3天的比赛日程,据此,将左上角部分的所有数字按其对应位置抄到右下角,将左下角的所有数字按其对应位置抄到右上角,这样,就分别安排好了选手1至选手4以及选手5至选手8在后4天的比赛日程,如图©所示。具有多个选手的情况可以依此类推。
这种解法是把求解个选手比赛日程问题划分成依次求解、、…、个选手的比赛日程问题,换言之,个选手的比赛日程是在个选手的比赛日程的基础上通过迭代的方法求得的。在每次迭代中,将问题划分为4部分:
(1)左上角:左上角为个选手在前半程的比赛日程;
(2)左下角:左下角为另个选手在前半程的比赛日程,由左上角加得到,例如个选手比赛,左下角由左上角直接加2得到,个选手比赛,左下角由左上角直接加4得到;
(3)右上角:将左下角直接抄到右上角得到另个选手在后半程的比赛日程;
(4)右下角:将左上角直接抄到右下角得到个选手在后半程的比赛日程;
五、用算法伪码描述:
void GameTable(int k, int a[100][100])
{
int n = 2;
a[1][1] = 1; a[1][2] = 2;
a[2][1] = 2; a[2][2] = 1;
for (int t = 1; t < k; t++)
{
int temp = n; n = n * 2;
for (int i = temp + 1; i <= n; i++)
for (int j = 1; j <= temp; j++)
a[i][j] = a[i - temp][j] + temp;
for ( i = 1; i <= temp; i++)
for (int j = temp + 1; j <= n; j++)
a[i][j] = a[i + temp][(j + temp) % n];
for ( i = temp + 1; i <= n; i++)
for (int j = temp + 1; j <= n; j++)
a[i][j] = a[i - temp][j - temp];
}
}
六、算法复杂度分析:
T(n)=O(n^2)
七、程序源代码:
对程序中变量进行说明:

#include <iostream>
#include <math.h>
using namespace std;
int calendar[100][100];  //日程表数组

void GameTable(int k, int a[100][100]);

void PrintTable(int k, int a[100][100]);
 
int main()
{
	int k;
	cout << "输入K的值:" ;
	cin >> k;
	cout << "日程表如下" << endl;
	GameTable(k, calendar);
	PrintTable(k, calendar);
	return 0;
}

void GameTable(int k, int a[100][100])
{
	// n=2^k(k≥1)个选手参加比赛
	//二维数组a表示日程安排,数组下标从1开始
	int n = 2;  //k=0,2个选手比赛日程可直接求得
	//求解2个选手比赛日程,得到左上角元素
	a[1][1] = 1; a[1][2] = 2;
	a[2][1] = 2; a[2][2] = 1;

	for (int t = 1; t < k; t++)
		//迭代处理,依次处理2^2, …, 2^k个选手比赛日程
	{
		int temp = n; n = n * 2;
		//填左下角元素
		for (int i = temp + 1; i <= n; i++)
			for (int j = 1; j <= temp; j++)
				a[i][j] = a[i - temp][j] + temp;
		//左下角元素和左上角元素的对应关系
//填右上角元素
		for ( i = 1; i <= temp; i++)
			for (int j = temp + 1; j <= n; j++)
				a[i][j] = a[i + temp][(j + temp) % n];
		//填右下角元素
		for ( i = temp + 1; i <= n; i++)
			for (int j = temp + 1; j <= n; j++)
				a[i][j] = a[i - temp][j - temp];
	}
}
 
void PrintTable(int k, int a[100][100])
{
	double n = pow((double)2, k);
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			cout << a[i][j] << "  ";
		}
		cout << endl<<endl;
	}
}

八、运行结果截图:

九、实验心得与体会:
程序主要运用了:数据输入、函数调用、函数传值、for循环以及二维数组等主要结构和功能。根据分治算法,将本问题进行了由小规模到大规模的求解设计,程序设计的关键点在于如何对问题进行划分和填充公式的归纳。在划分时,主要运用了两个for循环;在填充时,运用了两个for循环。
通过这次程序设计,加深了对分治算法的认识。解决具体问题时,程序故重要,但一个好的算法更加重要。

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值