循环日程表问题(分治)

---恢复内容开始---

题意 : 给出 n  = 2k个参赛者,要求每一个参赛者必须与其他 n-1 个选手各赛一次,每个选手一天只能赛一次,循环赛一共进行 n-1 天, 按照此要求设计一张比赛日程表, 使得该表有 n 行和 n-1 列,第 i 行 j 列为第 i 个选手第 j 天遇到的选手。

分析 : 刘大爷给出了一个分治的想法,当 k = 2也就是有 4 名选手的时候,左上角可以直接 1 和 2 去比,左下角是左上角每一个数 +2 得到,而右上角和右下角分别是左下角和左上角复制得到,也就是说只要我们得到了左上角,就能得到整张的合法表,一层一层递归下去,然后除了 k == 1 的时候特殊处理一下,其他层就进行复制操作!

以下代码自己瞎写的,所以不保证绝对正确

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10;
int G[maxn][maxn];
int k;
/*
     u m m+1 d
u    1 2  3  4
m    2 1  4  3
m+1  3 4  1  2
d    4 3  2  1
*/
inline void print()
{
    for(int i=1; i<=1<<k; i++){
        for(int j=1; j<=1<<k; j++){
            printf("%d ", G[i][j]);
        }puts("");
    }
}
void DFS(int up, int down, int k)
{
    if(k == 1){
        G[up][1]   = up;
        G[down][1] = down;
        G[up][2]   = down;
        G[down][2] = up;
        return ;
    }else DFS(up, down>>1, k-1);

    int val = 1<<(k-1);
    int m = down>>1;

    for(int ii=up, i=m+1; i<=down; i++, ii++){
        for(int j=up; j<=m; j++){
            G[i][j] = G[ii][j] + val;
        }
    }
    for(int ii=m+1, i=up; i<=m; i++, ii++){
        for(int jj=up, j=m+1; j<=down; j++, jj++){
            G[i][j] = G[ii][jj];
        }
    }
    for(int ii=up, i=m+1; i<=down; ii++, i++){
        for(int jj=up, j=m+1; j<=down; jj++, j++){
            G[i][j] = G[ii][jj];
        }
    }
}
int main(void)
{
    while(~scanf("%d", &k)){
        DFS(1, 1<<k, k);
        print();
    }
    return 0;
}

瞎 : 这种复制来复制去的操作,画个图,然后标个下标看着图打起来就很快而且出错率少

---恢复内容结束---

时间: 2025-01-07 14:25:58

循环日程表问题(分治)的相关文章

round robin schedule(循环日程表)

the source of the article:https://github.com/Fibird/Round-robin-schedule #include <iostream>#include <math.h> #define N 3 using namespace std; int main(){ int sche = pow(2.0, N); //the number of athlete int **arr = new int*[sche]; int bw = 1;

第八章 高效算法设计

分治法求最大连续和 注意范围是[x,y) #include<bits/stdc++.h> using namespace std; int maxsum(int *A,int x,int y){ if(y-x==1) return A[x]; int m=x+(y-x)/2; int maxs = max(maxsum(A,x,m),maxsum(A,m,y)); int v,L,R; v=0; L=A[m-1]; for(int i=m-1;i>=x;i--) L=max(L,v+=A

《入门经典》——6.24

有关递归与分治的几个问题: Q1:有一个2^k * 2^k的方格棋盘,恰有一个方格是黑色的,其他为白色的.你的任务是用包含3个方格的L型牌覆盖所有白色方格.黑色方格不能被覆盖,且任意一个白色方格不能同时被两个或更多牌覆盖. 分析:这道问题我们在<algorithm puzzle>一书的专栏中曾经有过介绍,它是分治的典型题目.其实要说分治和递推,它们是有区别和共性的.它们的共性是都是建立不同状态之间的关系,然是不同点在于,递推从一个状态出发,往往建立起来与另一个状态的关系,但是分治不同,从一个状

分治6--循环比赛日程表

分治6--循环比赛日程表 一.心得 递推方程式想清楚 二.题目及分析 问题描述: 设有n=2^k个运动员要进行网球循环赛.现要设计一个满足以下要求的比赛日程表: (1)每个选手必须与其他n-1个选手各赛一次:     (2)每个选手一天只能参赛一次:     (3)循环赛在n-1天内结束. 请按此要求将比赛日程表设计成有n行和n-1列的一个表.在表中的第i行,第j列处填入第i个选手在第j天所遇到的选手.其中1≤i≤n,1≤j≤n-1.8个选手的比赛日程表如下图:  算法思路:按分治策略,我们可以

分治与递归-循坏赛日程表

问题描述:设有n=2^k个运动员要进行网球循环赛.现要设计一个满足以下要求的比赛日程表: (1)每个选手必须与其他n-1个选手各赛一次:     (2)每个选手一天只能参赛一次:     (3)循环赛在n-1天内结束. 请按此要求将比赛日程表设计成有n行和n列的一个表.表中一行的第一个数为选手编号,其他元素分别为第1天~第n-1天所遇到的选手. 思路: 先打印出大表的左上角,然后在补充其他角的信息. 分治策略:找规律发现,由于n个选手的比赛日程可以通过n/2个选手设计的比赛日程表决定.所以就可以

经典算法学习-循坏赛日程表-分治^shu^递推^shu^压位lowbit

3jkE兆陆9遣G淘购http://www.zcool.com.cn/collection/ZMTg4ODI5ODg=.html X12NVLB曳咳5N7啥http://www.zcool.com.cn/collection/ZMTg4ODMwNjA=.html vX7乌始4咳咽1饰Xhttp://www.zcool.com.cn/collection/ZMTg4ODMxMDA=.html 19x75PF凸荷Khttp://www.zcool.com.cn/collection/ZMTg4ODM

算法之循环赛日程表

循环赛日程表 一.问题描叙 设有n=2^k个运动员,要进行网球循环赛.现在要设计一个满足以下要求的比赛日程表 (1).每个选手必须与其他n-1个选手各赛一场 (2).每个选手一天只能赛一次 (3).循环赛一共进行n-1天 二.问题分析 按此要求可将比赛日程表设计成n行n-1列的表,在表中第 i 行和第j 列处填入第 i 个选手在第 j 天所遇到的对手. 例如,当选手的人数为8人时,其比赛日程表如下图 算法分析:按分治策略,我们可以将所有的选手分为两半,则n个选手的比赛日程表可以通过n/2个选手的

算法交作业之循环和递归(二)

说明: 循环是学习编程过程中的不可或缺的一部分.同时递归同循环有着千丝万缕的关系. 求和函数示例: //求0到n的和.求和失败返回-1.否则返回结果. #include <iostream> //最常见的循环写法. long long Sum(unsigned int&& n){ long long sum = 0; for (unsigned index = 1; index <n+1; ++index) sum += index; return sum; } //递归

分治策略 - 最大子序列问题

自开始学习算法起,我感觉就是跪着把<算法导论>的代码看一遍.理解一遍然后敲一遍...说实话自己来写并且要求时间复杂度达到要求,我肯定是不能做到的,但我想前辈们辛苦积累的研究成果贡献出来也是为了让后人少走一些弯路,所以我的作用就是把前辈们的成果学习之后加以理解,然后积累经验,领悟到他们解决问题时的思路和灵感.还有就是把个人理解后的知识存储在不会忘记的地方作为复习备用... 当然什么是写博客呢,我个人认为是把所学的知识加上自己的理解然后用较为通俗的语言来解释一遍,至少这样才有可能把学到的东西变为自