• 【分治法】循环赛事表


    题意:

    2k个运动员进行网球循环赛,设计赛事表使得:

    • 每个选手与其他n-1个选手各赛一次
    • 每个选手每天只能赛一次
    • 循环赛在n-1天内结束

    日程表第i行第j列表示第i个选手在第j天遇到的选手

    分析:

    考虑k=3,n=8的情况,利用分治思想,将所有选手不停的分为两组,最终转化为只剩两个人进行比赛,再根据两个人的比赛安排得到整体赛事表。

    • 先列出要比赛的8位选手
      for(int i = 1; i <= 8; i++) a[1][i] = i;
    • 考虑表格前两行,两个人一组,将表格分成n/2块,将每一块的左上角元素抄到右下角,右上角元素抄到左下角
    • 继续考虑前四行,四个人一组,将表格分成n/4块,同理将每一块的左上角元素抄到右下角,右上角元素抄到左下角
    • 最后考虑前八行,八个人一组,将表格看成一个整体,同理将左上角的元素抄到右下角,右上角元素抄到左下角
    • 最终获得日程表
    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

    代码:

    #include<cstdio>
    #include<cmath>
    #include<iostream>
    using namespace std;
    const int maxn = 10005;
    int a[maxn][maxn];
    int main (void)
    {
        int k, m = 1;
        cin>>k;
        int t = pow(2,k);
        int n = t;
    
        //第一行
        for(int i = 1; i <= n; i++)  a[1][i] = i;
    
        //依次分块,并将每块的左上角元素抄到右下角,右上角抄到左下角
        for(int i = 1; i <= k; i++){
            n /= 2;
            for(int p = 1; p <= n; p++){
                for(int j = 1; j <= m; j++){
                    for(int k = 1; k <= m; k++){
                        a[j+m][k+2*m*(p-1)] = a[j][m+k+2*m*(p-1)];
                        a[j+m][m+k+2*m*(p-1)] = a[j][k+2*m*(p-1)];
                    }
                }
            }
            m *= 2;
        }
    
        //打印表格
        for(int i = 1; i <= t; i++){
            for(int j = 1; j <= t; j++){
                cout<<a[i][j]<<' ';
            }
            cout<<endl;
        }
    }
    
  • 相关阅读:
    vbscript 语言通过序列和ADODB实现取号不重复
    arcgisserver成功发布服务后,浏览服务,无地图显示
    GUID的获取
    EasyUi 表格自适应宽度
    接口隔离原则
    依赖倒置原则
    开放封闭原则
    单一职责原则
    python-函数基础
    python -流程控制
  • 原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758853.html
Copyright © 2020-2023  润新知