USACO-Section2.1 sort3[排序][递归]

题目大意:

排序是一种很频繁的计算任务。现在考虑最多只有三值的排序问题。一个实际的例子是,当我们给某项竞赛的优胜者按金银铜牌排序的时候。在这个任务中可能的值只有三种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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值