zoukankan      html  css  js  c++  java
  • [算法]循环赛日程表

    问题描述:

    设有n=2k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表:

    1. 每个选手必须与其他n-1个选手各赛一次;
    2. 每个选手一天只能参赛一次;
    3. 循环赛在n-1天内结束。

    请按此要求将比赛日程表设计成有n行和n-1列的一个表。在表中的第i行,第j列处填入第i个选手在第j天所遇到的选手。其中1≤i≤n,1≤j≤n-1。

    -------------------------------------------------------------------------

    解答:

    这个算法被划分到了分治算法的例子,的确它包含分治算法的意思,但是如果从构建规则出发,而不是从分治思想出发,我怎么感觉想起来更不绕弯呢!

    其实这个表的构建很容易。首先有个数组T,n行n列,第一列第一行填入数字1,初始就是这个样子的。

    1

    此时k=0,由它向下扩展,向右扩展,向右下扩展就变成了k=1的情况,即由一行一列变成二行而列,如何扩展呢?

    向下:原始值(左上角)加1(k)向下搬

    右上:把刚才填充上的左下的搬上去

    右下:把原来的,左上的搬下去。

    1

    2

     

    2

    1

     
         

    按照这个规律,当K=2的时候,应该是这个样子的

    1

    2

    3

    4

     

    2

    1

    4

    3

     

    3

    4

    1

    2

     

    4

    3

    2

    1

     
             

    当K=3的时候,应该是这个样子的

    1

    2

    3

    4

    5

    6

    7

    8

    2

    1

    4

    3

    6

    5

    8

    7

    3

    4

    1

    2

    7

    8

    6

    6

    4

    3

    2

    1

    8

    7

    5

    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

    把第一列去掉就是我们想要的8个运动员的比赛日程表。

    想通了,代码就非常容易了。

    /// <summary>
            /// 生成比赛日程表
            /// </summary>
            /// <param name="k">运动员数为2的n次方</param>
            public void GenerateTable(int n)
            {
                int N=(int)Math.Pow(2,n);
                int[,] T=new int[N,N];
                T[0, 0] = 1;
                for (int k = 0; k < n; k++)
                {
                    int end=(int)Math.Pow(2,k)-1;  //左上小方块结束的行和列
                    int end2 = (int)Math.Pow(2,k+1) - 1; //本次填充结束的行和列
                    int baseNum = (int)Math.Pow(2,k); 
                    //左下填充
                    for (int i = end + 1; i <= end2; i++)
                    {
                        for (int j = 0; j <= end; j++)
                        {
                            T[i, j] = T[i - baseNum, j] + baseNum;
                        }
                    }
                    //右上填充
                    for (int i = 0; i <= end; i++)
                    {
                        for (int j = end + 1; j <= end2; j++)
                        {
                            T[i, j] = T[i + baseNum, j - baseNum];
                        }
                    }
                    //右下填充
                    for (int i = end + 1; i <= end2; i++)
                    {
                        for (int j = end + 1; j <= end2; j++)
                        {
                            T[i,j]=T[i-baseNum,j-baseNum];
                        }
                    }
                }
                //output
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < N; i++)
                {
                    for (int j = 1; j < N; j++)
                    {
                        sb.Append(T[i,j]+" ");
                    }
                    sb.Append("
    ");
                }
                Console.WriteLine(sb);
                Console.ReadKey();
    
            }
    

      

  • 相关阅读:
    【LOJ6041】「雅礼集训 2017 Day7」事情的相似度(用LCT维护SAM的parent树)
    【BZOJ1171】大sz的游戏(线段树+单调队列)
    2019年4月训练记录(4.07~4.22)
    【BZOJ4766】文艺计算姬(prufer序列)
    【BZOJ4573】[ZJOI2016] 大森林(LCT)
    2019.03.19 ZJOI2019模拟赛 解题报告
    【牛客挑战赛30D】小A的昆特牌(组合问题抽象到二维平面)
    【洛谷2624】[HNOI2008] 明明的烦恼(Python+利用prufer序列结论求解)
    【洛谷2290】[HNOI2004] 树的计数(Python+利用prufer序列结论求解)
    初识prufer序列
  • 原文地址:https://www.cnblogs.com/orchid/p/3275747.html
Copyright © 2011-2022 走看看