欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于比赛日程的安排

程序员文章站 2022-05-13 19:38:04
...

循环赛日程表


题目:
设有n个运动员要进行网球循环比赛。设计一个满足要求比赛的算法
(1)每个选手必须和其他n-1位选手进行比赛
(2)每个选手一天只能参加一场比赛(也可以不参加)
(3)当n为偶数时要进行n-1天的比赛;当n为奇数时要进行n天的比赛
分治法代码如下:

#include <iostream>

using namespace std;
int b[100];//随便设置的空间根据问题需要设置
int a[20][20];
void copy1(int n){//对偶数的处理
    int m = n/2;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=m;j++){
            a[i][j+m] = a[i][j]+m;
            a[i+m][j] = a[i][j+m];
            a[i+m][j+m] = a[i][j];
        }
    }
}
void copyodd(int n){//对奇数的处理
    int m = n/2;
    for(int i=1;i<=m;i++){
        b[i] = m+i;//设置辅助数组
        b[m+i] = b[i];
    }
    for(int i =1;i<=m;i++){
        for(int j=1;j<=m+1;j++){
        //针对左上角和左下角的操作
        if(a[i][j]>m){//此处存在是为了将轮空的置为相应的值
            /*输出的控制台中的数据 input=10
            a[i][j]的变化
            3 1 4 :4-->4
            3 2 3 :4-->5
            3 3 2 :4-->6
            5 1 6 :6-->6
            5 2 5 :6-->7
            5 3 2 :6-->8
            5 4 3 :6-->9
            5 5 4 :6-->10
            */
            //1:cout<<m<<" "<<i<<" "<<j<<" "<<":"<<a[i][j];
            a[i][j] = b[i];
            //cout<<"-->"<<a[i][j]<<endl;
            //cout<<m<<" "<<m+i<<" "<<j<<" "<<":"<<a[m+i][j];
            a[m+i][j] = (b[i]+m)%n;
            //cout<<"-->"<<a[m+i][j]<<endl;
            /*输出的控制台中的数据 input=10
            a[m+i][j]的前后变化
            3 4 4 :1-->1
            3 5 3 :0-->2
            3 6 2 :0-->3
            5 6 6 :1-->1
            5 7 5 :0-->2
            5 8 2 :0-->3
            5 9 3 :0-->4
            5 10 4 :0-->5
            */
        }
        else
            a[m+i][j] = a[i][j]+m;//针对左下角进行处理
            //if else 语句的设置主要是为了 a[i][j]+m 不超过n 
        }
        for(int j=2;j<=m;j++){
            a[i][m+j] = b[i+j-1];//针对右上角操作
            a[b[i+j-1]][m+j] = i;//针对右下角操作
        }
    }
}
int odd(int n){
    return n&1;
}
void makecopy(int n){
    if(n/2>1&&odd(n/2))
        copyodd(n);
    else
        copy1(n);
}
void tournament(int n){
    if(n==1){
        a[1][1] = 1;
        return ;
    }
    if(odd(n)){
        tournament(n+1);//无法将奇数分成相等的两份引入虚拟的n+1
        return;
    }
    tournament(n/2);
    makecopy(n);
}
int main()
{
    int n;
    cin>>n;
    tournament(n);
    if(!odd(n)){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)
            cout<<a[i][j]<<'\t';
        cout<<endl;
    }}
    else{
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n+1;j++)
                cout<<a[i][j]<<'\t';
            cout<<endl;
        }
    }

    return 0;
}
/*测试n=10
1       2       3       4       5       6       7       8       9       10
2       1       5       3       7       4       8       9       10      6
3       8       1       2       4       5       9       10      6       7
4       5       9       1       3       2       10      6       7       8
5       4       2       10      1       3       6       7       8       9
6       7       8       9       10      1       5       4       3       2
7       6       10      8       2       9       1       5       4       3
8       3       6       7       9       10      2       1       5       4
9       10      4       6       8       7       3       2       1       5
10      9       7       5       6       8       4       3       2       1
*/

注:当选手轮空时,将会显示数字n+1

相关标签: 分治法