#include "iostream"
#include "cmath"
using namespace std;
//---------------------------------
//多边形法
//---------------------------------
int arr[20][20];
int b[20];
int odd(int n) //如果是奇数,返回1,否则返回0
{
return n & 1;
}
void construct(int n)
{
if (n == 1)
return;
int m = odd(n) ? n : n - 1; //如果n是奇数,转换为偶数
arr[n][1] = n;
for (int i = 1; i <= m; i++)
{
arr[i][1] = i; //第1列,表示第i个选手
b[i] = b[i + m] = i + 1;
}
for (int i = 1; i <= m; i++) //第2列~第n列,相当于旋转多边形,确定哪个选手和哪个选手比赛
{
arr[1][i + 1] = b[i]; //每列中的第一个数字
arr[b[i]][i + 1] = 1;
for (int j = 1; j <= m / 2; j++) //每列中的其余数字
{
arr[b[i + m - j]][i + 1] = b[i + j]; //相当于水平线连起来的两个顶点
arr[b[i + j]][i + 1] = b[i + m - j];
}
}
}
//---------------------------------
//分治法:根据结果反推出来的
//---------------------------------
int a[20][20];
void copy(int n);
void tourna(int n){
if(n==1){
a[1][1]=1;
return;
}
tourna(n/2);
//将左上角递归计算出的小块中的所有数字按其相对位置抄到右下角,
//将右上角小块中的所有数字加 n/2 后按其相对位置抄到左下角,
//将左上角的小块抄到右下角
copy(n);
}
/*
1 2 3 4 5 6 7 8
2 1 4 3 6 5 8 7
3 4 1 2 7 8 5 6
4 3 2 1 8 7 6 5
5 6 7 8 1 2 3 4
6 5 8 7 2 1 4 3
7 8 5 6 3 4 1 2
8 7 6 5 4 3 2 1
*/
void copy(int n){
int m=n/2;
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
a[i+m][j+m] = a[i][j];//将左上角的小块抄到右下角
//将左上角的小块加 n/2 后抄到右上角
a[i][j+m] = a[i][j]+m;
//将左下角小块中的所有数按其相对位置抄到右上角
a[i+m][j] = a[i][j+m];
}
}
}
int main()
{
int n;
// cout << "输入参加比赛的运动员数量:";
// cin >> n;
n = 8;
construct(n);
cout << "多边形法,循环赛日程表为:\n";
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
cout << arr[i][j] << "\t";
cout << endl;
}
tourna(n);
cout << "分治法,循环赛日程表为:\n";
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
cout << a[i][j] << "\t";
cout << endl;
}
return 0;
}
002-3算法笔记【分治】-习题2-15球赛日程表
于 2022-04-24 09:20:33 首次发布