题目:ACdream 1038 (想法+排序)
思路:
1. 这一题的题意是将打乱了的数字归于原位,每一次交换2个数字的位置,如果有k个交换机会,最多有几个数字归于原位。
2. 这一题你会发现无论数字怎样打乱都会形成一个一个的环,假设由n个数字组成一个环,那么只需要交换n-1次即可将所有的位置还原,如果不足n-1次的交换机会,那么你至少可是使k个数字还原。
3. 由于题目是k次使最多的数字归位,那么在事先统计出了各个环的数量后,就排序,先解决小环,再解决大环,就这样。
4. 那么这一题的流程就分为:输入->统计环数->将环数排序->从小到大解决->输出
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Max 100001
int flag[Max], huan[Max], number[Max];
int cmp( const void *a, const void *b)
{
return *(int*)a - *(int*)b;
}
int main()
{
int n,k;
int result,temp;
int i, nu,cicle; /*控制数组*/
while (scanf("%d%d",&n,&k)!=EOF)
{
result=0;
memset(flag, 0, sizeof(flag));
memset(huan, 0, sizeof(huan));
memset(number, 0, sizeof(number));
for (i=0; i<n; i++)
{
scanf ("%d",&number[i]);
if(i==number[i]) /*将已经归位原位的数字统计*/
{
flag[i]=1;
result++;
}
}
nu=0;
for( i=0; i<n ;i++)
{
cicle=0; /*统计环的大小,环的个数*/
temp=i;
while (flag[temp]==0)
{
cicle++;
flag[temp]=1;
temp=number[temp];
}
if(cicle>1)
huan[nu++]=cicle;
}
qsort( huan, nu, sizeof (huan[0]), cmp); /*按照换的大小排序*/
for( i=0; i<nu ; i++) /*统计归位的数字*/
{
if ( k<(huan[i]-1))
{
result=result+k;
break;
}
else
{
result+=huan[i];
k=k-(huan[i]-1);
}
}
printf("%d\n",result);
}
return 0;
}
/**************************************************************
Problem: 1038
Language: C
Result: Accepted
Time:100 ms
Memory:2080 kb
****************************************************************/