题目大意:
排序是一种很频繁的计算任务。现在考虑最多只有三值的排序问题。一个实际的例子是,当我们给某项竞赛的优胜者按金银铜牌排序的时候。在这个任务中可能的值只有三种1,2和3。我们用交换的方法把他排成升序的。写一个程序计算出,给定的一个1,2,3组成的数字序列,排成升序所需的最少交换次数。
样例输入:
9
2
2
1
3
3
3
2
3
1
样例输出:
4
题解:
参考了NOCOW上的一个解,还有大佬的补充,我做了一个自己的想法。
![]()
这是NOCOW 上的。我自己的想法是对如上的数对进行排序,如数对(a,b),优先对a排序,a相同对b排序,然后从前到后用递归找环。
我认为这样找出的环都是从大到小的,简单的想,我们从前向后,肯定是先出现的环就是小环。下面简单说一下:
大佬说 可能会出现(1,2),(2,3),(3,2),(2,3),(3,1))这样的环,但是按照我的方法,(3,2)不会出现在(3,1)前面,所以(1,2) (2,3) (3,1)就停止了,出现的环就是小环。
具体证明我搞不定,而且过数据的时候,1000的数据过了,50的没过去,我也看了半天没看出来哪里有个小问题。最后po上50数据。
C++
/*
ID:mujinui1
LANG:C++
TASK:sort3
*/
#include<fstream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,flag,temp,k=0,t=0;
int a[1100],b[1100],c[1100][2],ans[1100];
bool mark[1100];
void dfs(int m){// 递归找换
if(c[m][1]==c[temp][0]){
return ;
}
for(int i=m+1;i<k;i++){
if(c[i][0]==c[m][1]&&mark[i]==true){
mark[i]=false;
flag++;
dfs(i);break;
}
}
return ;
}
int main(){
ifstream fin("sort3.in");
ofstream fout("sort3.out");
memset(mark,true,sizeof(mark));
fin>>n;
for(int i=0;i<n;i++){
fin>>a[i];
b[i]=a[i];
}
sort(a,a+n);
for(int i=0;i<n;i++){
if(a[i]!=b[i]){
c[k][0]=a[i];
c[k++][1]=b[i];
}
}
for(int i=0;i<k-1;i++){//忽略掉我的排序方法,谢谢
for(int j=i;j<k;j++){
if(c[j][0]<c[i][0]){
temp=c[j][0];
c[j][0]=c[i][0];
c[i][0]=temp;
temp=c[j][1];
c[j][1]=c[i][1];
c[i][1]=temp;
}
if(c[j][0]==c[i][0]&&c[j][1]<c[i][1]){
temp=c[j][0];
c[j][0]=c[i][0];
c[i][0]=temp;
temp=c[j][1];
c[j][1]=c[i][1];
c[i][1]=temp;
}
}
}
for(int i=0;i<k;i++){
flag=1;
if(mark[i]==true){
//cout<<i<<endl;
temp=i;
mark[i]=false;
dfs(i);
ans[t++]=flag;
}
}
temp=0;
for(int i=0;i<t;i++){
temp=temp+ans[i];
}
fout<<temp-t<<endl;
return 0;
}
50 的那一组数据,请大佬指教(●ˇ∀ˇ●)
50
1
1
1
3
1
3
2
1
2
3
3
1
3
2
1
1
2
3
2
2
3
3
2
3
2
2
3
1
1
1
1
1
1
1
3
1
1
2
2
3
1
1
3
3
2
1
1
1
3
2