圆桌会议
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3136 Accepted Submission(s): 2179
Problem Description
HDU ACM集训队的队员在暑假集训时经常要讨论自己在做题中遇到的问题.每当面临自己解决不了的问题时,他们就会围坐在一张圆形的桌子旁进行交流,经过大家的讨论后一般没有解决不了的问题,这也只有HDU ACM集训队特有的圆桌会议,有一天你也可以进来体会一下哦:),在一天在讨论的时候,Eddy想出了一个极为古怪的想法,如果他们在每一分钟内,一对相邻的两个ACM队员交换一下位子,那么要多少时间才能得到与原始状态相反的座位顺序呢?(即对于每个队员,原先在他左面的队员后来在他右面,原先在他右面的队员在他左面),这当然难不倒其他的聪明的其他队友们,马上就把这个古怪的问题给解决了,你知道是怎么解决的吗?
Input
对于给定数目N(1<=N<=32767),表示有N个人,求要多少时间才能得到与原始状态相反的座位顺序(reverse)即对于每个人,原先在他左面的人后来在他右面,原先在他右面的人在他左面。
Output
对每个数据输出一行,表示需要的时间(以分钟为单位)
Sample Input
4 5 6
Sample Output
2 4 6
Author
Eddy
Source
解析:首先需要明确的一点,这道题中队员是环形排列,并非线型。不过,我们可以通过适当的转换,使得环形问题称为线型文体。
1.从顺序排列转换成逆序排列:
1 2 。。。。n-1 n ===>n n-1 。。。。 2 1
所需的时间为n*(n-1)/2。
注意,在c++中,整数乘除得到的依然是整数,即有:1/5==2/5==3/5==0,所以这里就可以不用讨论n的奇偶性了。
2.对于n==4的环形排列,解决方案如下:
① ③ ② ④
| | ===> | |
② ④ ① ③
将1与2逆序排列,时间t1=1,将3与4逆序排列,时间t2=2,ans=t1+t2=2。
由归纳法可得:
若1与2之间存在n-2个队员顺序排列,3与4之间存在m-2个队员顺序排列,这m+n个队员构成一个环。解决方案即:将1与2之间(包括1、2)的队员逆序排列,时间t1,将3与4之间的队员逆序排列,时间t2,ans=t1+t2。
即最终的解决方案为:将n个队员分成两部分,一部分为r,tr=r*(r-1)/2,一部分为x,tx=x*(x-1)/2,
ans=r*(r-1)/2+x*(x-1)/2(N>=4)
当1<=n<4时,上述公式仍然成立,所以:
ans=r*(r-1)/2+x*(x-1)/2(n>=1)
最后,虽然题目上没说,但最终输出答案时我们还是应当输出所需的最小时间,即取:r=n/2,x=n-r;
代码如下:
#include<cstdio>
using namespace std;
void init()
{
freopen("hdu1214.in","r",stdin);
freopen("2hdu1214.out","w",stdout);
}
void work()
{
int n,i,j,k;
while(scanf("%d",&n)==1)
{
i=(n>>1),j=n-i;
k=i*(i-1)/2+j*(j-1)/2;
printf("%d\n",k);
}
}
int main()
{
init();
work();
return 0;
}