说明
设有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 三天
输入格式
每个测试文件只包含一组测试数据,每组输入数据为一个正整数n(n<=6)。
输出格式
对于每组输入数据,输出比赛安排,从第一天的安排开始,每天占一行,每行开头先输出天号,再输出当天的安排,优先给队伍编号小的队伍安排比赛,具体格式见样例输出。
样例
输入数据 1
2
输出数据 1
<1>1-2,3-4
<2>1-3,2-4
<3>1-4,2-3
解题思路
因为本题的数据范围较小(2的n次方,n<=6),所以我们可以选择暴力一点的方法解决。从题中可知每一个球队都要与另外几个球队打一次比赛并且与每个球队只打一次,所以我们可以设一个bool类型的二维数组f [ i ][ j ]表示 i 球队和 j 球队是否比过赛。又从每天的比赛来看,每天每个球队都要打一场比赛,所以我们又可开一个一维数组 a [ i ]判断每天每个球队是否打比赛过,并且在每一天开始都将数组a清零。
根据此思路,模拟一遍题意,代码就很容易得出:
#include<iostream>
#include<cmath>
#include<cstring>
#define MAXN 65
using namespace std;
bool f[MAXN][MAXN];//表示第i天和第j天比过赛没
bool day[MAXN];//表示当天i队比过赛没
int main()
{
int n;
cin >> n;
int m=pow(2,n);//多少个队伍
int t=1;//第几天
while(t<m)//只需比m-1天
{
cout << "<" << t++ << ">";//输出第几天
memset(day,0,sizeof(day));//新的一天新的比赛开始
int r=0;//计算有几个队比过赛了
for(int i=1;i<=m;i++)
{
if(day[i])//如果i队比过,跳过
continue;
for(int j=i+1;j<=m;j++)
{
if(day[j] || f[i][j])//如果j队比过,或者i和j队比过,跳过
continue;
day[i]=day[j]=f[i][j]=1;//比过赛的都赋值为1
r+=2;//每次比赛都有两个队比过
cout << i << "-" << j;
if(r<m)//如果今天还没比完
cout << ",";
else//比完了
cout << endl;
break;//只要找到一个j队与i队匹配,就可跳出j循环(因为i队比过赋值为1,无需再找)
}
}
}
return 0;
}
注:新手写题,如有错误请各位大佬及时指出(谢谢)。