Tournament
题目描述:
您正在安排比赛。 有n个团队。 每对球队都有
n
(
n
−
1
)
2
\frac {n(n-1)} {2}
2n(n−1)个比赛。 您可以每天安排比赛。 对于每支球队,它将在第一场比赛举行的当天到达,并在最后一场比赛结束后离开。
例如,有3个团队,日程表是
(
1
,
2
)
,
(
1
,
3
)
,
(
2
,
3
)
(1,2),(1,3),(2,3)
(1,2),(1,3),(2,3)。 一队将在第一天到达,在第二天离开。它将停留两天。 第二小组将停留三天。 第三队将停留两天。
您想找到一个时间表,以减少他们停留的天数。
输入描述:
第一行包含一个整数
T
(
1
≤
T
≤
30
)
T(1 \leq T \leq 30)
T(1≤T≤30)-测试用例的数量。
对于每个测试用例,第一行包含一个整数
n
(
2
≤
n
≤
300
)
n(2 \leq n \leq 300)
n(2≤n≤300)。
输出描述:
对于每个测试用例,输出 n ( n − 1 ) / 2 n(n-1)/2 n(n−1)/2行。 每行包含两个整数 ( u , v ) ( 1 ≤ u , v ≤ n ) (u,v)(1 \leq u,v \leq n) (u,v)(1≤u,v≤n)------您今天计划的比赛。
样例输入:
2
3
4
样例输出:
1 2
1 3
2 3
1 2
1 3
1 4
2 3
2 4
3 4
思路:
分治。
我们首先想到二重循环暴力求解:
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
printf("%d %d",i,j);
交上去就是一发WA…
先WA一发清醒一下后再仔细分析一下题目:
如果每次我们让第一队先走,那么我们会发现标号越大的队伍住的天数越多,这明显是不合理的…
首先我们想到:1队越早走,后面的队伍住的总时间就越长,所以我们要尽量折中每个队伍的住的时间。
于是我们就想到如下的构造方法:
- 首先把n个人分成两半
- 然后让前一半的人开始打比赛
- 然后让前一半的人和后一半的人打比赛
- 然后后一半的人开始打比赛
按照上面的WA的暴力代码和上面的构造策略,以n=6为例:
暴力: 构造:
1 2 1 2
1 3 1 3
1 4 2 3
1 5 1 4
1 6 2 4
2 3 3 4
2 4 1 5
2 5 2 5
2 6 3 5
3 4 4 5
3 5 1 6
3 6 2 6
4 5 3 6
4 6 4 6
5 6 5 6
明显构造的方法较优。
但是也不止这么一种构造方法,如果两个比赛顺序换一换是等价的当然也可以。
这题是spj,所以只需要输出任意一组答案。
A C AC AC C o d e Code Code:
#include<bits/stdc++.h>
using namespace std;
int t,n;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=2;i<=n/2;++i)
for(int j=1;j<i;++j)
printf("%d %d\n",j,i);
for(int i=n/2+1;i<n;++i)
for(int j=1;j<=n-i;++j)
printf("%d %d\n",j,i);
for(int i=1;i<=n/2;++i)
for(int j=n-i+1;j<=n;++j)
printf("%d %d\n",i,j);
for(int i=n/2+1;i<n;++i)
for(int j=i+1;j<=n;++j)
printf("%d %d\n",i,j);
}
}