1180:循环赛日程表

Description
度娘举办了一个游戏的竞技赛,比赛采用循环赛制。现有 n 名选手报名参加了比赛,因为是循环赛制,所以每个选手都必须和其他的 n-1 个选手比赛一次,而为了保证参赛选手的休息,每个选手每天只能进行一场比赛。度娘一下子被赛制绕晕了,而BOSS又要求比赛在 n-1 天内完成。度娘请你帮助她设计比赛的日程表。
日程表要求为 n 行 n 列的表格,i 行 j 列表示第 i 个选手在第 j 天所遇到的选手。

Input
输入为单组数据,包含一个正整数 n ( n = 2k, 0 < k <= 5)

Output
输出一个 n 行 n 列的日程表 每个数字之间用空格隔开(每行的末尾没有空格)

Sample Input
8

Sample Output
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
假设n位选手被顺序编号为1,2,3,…,n,比赛的日程表是一个n行n-1列的表格,i行j列的表格内容是第i号选手在第j天的比赛对手。根据分而治之的原则,可从其中一半选手(2^(n-1位)的比赛日程,导出全体n位选手的日程,最终细分到只有两位选手的比赛日程出发。

可假设只有8位选手参赛,若1至4号选手之间的比赛日程填在日程表的左上角(4行3列),5至8号选手之间的比赛日程填在日程表的左下角(4行3列);那么左下角的内容可由左上角的对应项加上数字4得到。至此,剩余的右上角(4行4列)是为编号小的1至4号选手与编号大的5至8号选手之间的比赛日程安排。

例如,在第4天,让1至4号选手分别与5至8号选手比赛,以后各天,依次由前一天的日程安排,让5至8号选手“循环轮转”即可。最后,比赛日程表的右下角的比赛日程表可由,右上角的对应项减去数字 4得到。

#include <stdio.h>
int ans[50][50];
void print(int n){
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(j==0)
                printf("%d",ans[i][j]);
            else
                printf(" %d",ans[i][j]);
        }
        printf("\n");
    }
}
void cal(int n){
    int m=n/2;
    for(int i=0;i<m;i++)
        for(int j=0;j<m;j++){
            ans[i+m][j]=ans[i][j]+m;
            ans[i][j+m]=ans[i+m][j];
            ans[i+m][j+m]=ans[i][j];
        }
}
void solve(int n){
    if(n==1){
        ans[0][0]=1;
        return;
    }
    solve(n/2);
    cal(n);
}
int main(){
    int n;
    scanf("%d",&n);
    solve(n);
    print(n);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值