循环日程表问题(分治)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了循环日程表问题(分治)相关的知识,希望对你有一定的参考价值。
---恢复内容开始---
题意 : 给出 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;
}
瞎 : 这种复制来复制去的操作,画个图,然后标个下标看着图打起来就很快而且出错率少
---恢复内容结束---
以上是关于循环日程表问题(分治)的主要内容,如果未能解决你的问题,请参考以下文章