---恢复内容开始---
题意 : 给出 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