zoukankan      html  css  js  c++  java
  • 循环赛日程表_分治法

    题目:

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

      1、每个选手必须与其他n-1个选手各比赛一次。

      2、每个选手一天只能赛一次。

      3、循环赛一共进行n-1天。

    按照此要求可以将比赛日程表设计成一个n*n的二维表,第一列表示选手,接下来的每一列依次表示将要比赛的每一天选手。下面以8个选手为例:

    思路:

      按照分治法,可将所有选手进行二分,n个选手的比赛安排可通过n/2个选手的日程表来决定。递归地用这种一分为二的策略对选手进行分割,知道只剩两个选手,日程表显然直接安排即可。

    下图为8个选手的比赛日程表:

       

           图1

    算法步骤:

      1、利用一个for循环初始化选手1的日程安排,即图1中的第一行。

      2、根据选手1的日程安排来安排选手2。此刻为最小规模,以相邻的每两天即四个最小单元为一组,例如选手一第一天要跟选手2比赛,那么相应选手2也要跟选手1比赛,所以将图1中的第一行第一列序号抄到第二行第二列,将第一行第二列序号抄到第二行第一列。依次,第3、4列,第5、6列,第7、8列也是。

      3、根据选手1、2的日程安排可以按照左上角数据抄到右下角,右上角数据抄到左下角安排出选手3、4的日程。

      4、最后根据前四选手,可以将所有人的日程表都安排出来。

    下面是java实现完整代码:

     1 package competition;
     2 
     3 import java.util.Scanner;
     4 
     5 public class Com {
     6     private static Scanner scanner;
     7 
     8     public static void main(String [] args) {
     9         int k; //注意,n才是选手的人数,k只是问题要划分的子问题规模数,即n=2^k
    10         System.out.println("输入k:");
    11         scanner = new Scanner(System.in);
    12         k=scanner.nextInt();
    13         int a[][]=new int[pow(2,k)+1][pow(2,k)+1];
    14         table(k, a);
    15         for(int i=1; i<pow(2,k)+1; i++){
    16             for(int j=1; j<pow(2,k); j++){
    17                 System.out.print(a[i][j]+" ");
    18             }
    19             System.out.println(a[i][pow(2,k)]);
    20         }
    21     }
    22     
    23     static void table(int k, int [][]a){
    24         int n=pow(2,k);
    25         for(int i=1; i<=n; i++) a[1][i]=i;
    26         int m=1;//定义M为记录每一次填充时i、j的起始填充位置
    27         for(int s=1; s<=k; s++){//分治规模
    28             n/=2;
    29             for(int t=1; t<=n; t++)//t是每一层分治中进行对称的单位的个数
    30                 for(int i=m+1; i<=2*m; i++)//控制行
    31                     for(int j=m+1; j<=2*m; j++){//控制列
    32                         a[i][j+(t-1)*m*2]=a[i-m][j+(t-1)*m*2-m];//右下角的值等于左上角的值 
    33                         a[i][j+(t-1)*m*2-m]=a[i-m][j+(t-1)*m*2];//左下角的值等于右上角的值 
    34             }
    35             m*=2;
    36         }
    37     }
    38     
    39     static int pow(int a, int n) {//幂函数
    40         int res=1;
    41         for(int i=0; i<n; i++)
    42             res*=a;
    43         return res;
    44     }
    45 }
  • 相关阅读:
    C#与C++中struct和class的小结
    C#中string的小结
    树的一些操作——遍历,前序和中序建立后续
    一个快速、高效的Levenshtein算法实现——代码实现
    整数拆分
    阶乘结果中0的个数
    普莱菲尔密码矩阵生成算法
    CTF密码学总结
    盲文对照表
    实验吧-古典密码
  • 原文地址:https://www.cnblogs.com/LieYanAnYing/p/11628008.html
Copyright © 2011-2022 走看看