2023-3-28 每日一题 比赛安排
1. 题目描述
设有2^ n (n <= 6) 队进行单循环比赛,计划在2^ n – 1天内完成,每个队每天进行一场比赛。设计一个比赛的安排,使在2^ n – 1天内每个队都与不同的对手比赛。
例如n=2时的比赛安排:
队 1 2 3 4
比赛
1 —— 2 3 —— 4 一天
1 —— 3 2 —— 4 二天
1 —— 4 2 —— 3 三天
2. 输入格式
每个测试文件只包含一组测试数据,每组输入数据为一个正整数n(n <= 6)。
3. 输出格式
对于每组输入数据,输出比赛安排,从第一天的安排开始,每天占一行,每行开头先输出天号,再输出当天的安排,优先给队伍编号小的队伍安排比赛,具体格式见样例输出。
4. 样例
4.1 输入样例
2
4.3 输出样例
<1>1-2,3-4
<2>1-3,2-4
<3>1-4,2-3
5. 题解
5.1 文字描述
先写一个循环遍历比赛的天数(即从 1 到 2^ n -1),再写一个二重循环遍历比赛的队伍(即 1 到 2^ n)。用一个一维数组用于判断这个队伍是否在这一天已经被遍历,即已经比过赛。(即若 a[i] == 1 则代表着 i 这个队伍今天已经比过赛)。由于是存储当天是否比过赛,则枚举天数时,需要将数组全部归为0再定义一个二维数组用于判断是否两支队伍已经比过赛(即若 sum[i][j] == 1 则代表着 i 和 j 已经比过赛)。
5.2 上代码
#include<iostream>
#include<cstring>
using namespace std;
int a[10010], sum[10010][10010];
int main()
{
int n;
cin >> n;
// 枚举比赛天数 1 - 2^n-1
for(int i = 1; i <= (1 << n)-1; i++)
{
// 将数组全部初始化为 0
memset(a, 0, sizeof(a));
int cnt = 0;
// 按格式输出
cout << "<" << i << '>';
for(int j = 1; j <= (1 << n); j++)
{
for(int k = j+1; k <= (1 << n); k++)
{
if(!sum[j][k] && !a[k] && !a[j])
{
sum[j][k] = a[j] = a[k] = 1;
cout << j << '-' << k;
cnt++;
if(cnt >= 1 && cnt < (1 << n)/2)
cout << ',';
}
}
}
cout << endl;
}
return 0;
}