USACO 2.1.3 Sorting a Three-Valued Sequence解题报告

原题链接:

一看这道题就想到了离散上学的置换群,按置换群做了做,果然AC了!

先讲一下思考过程:             

       index:    1   2   3   4   5   6   7   8   9                     

     原数据:    2   2   1   3   3   3   2   3   1                               

     排序后:    1   1   2   2   2   3   3   3   3                                   

    分组后  index:           1    3               2    9    5               4    7                     6       8      

                                       2    1               2    1    3               3    2                     3       3

                                       1    2               1    3    2               2    3                     3       3

                              从上面的分组可看出第一组和第三组交换一次,第二组和第五组交换一次,第五组再和第九组交换一次,第四组和第七组交换一次,这样一共交换了4次,

                      就是答案了!

                             关键是如何进行分组呢?这就用到了离散上的知识,将群转换为轮换和对换之积的形式,然后分别计算出对换或轮换中数的个数再减一就是交换的次数,把

                      所有次数累加就是总的交换次数了。但是要注意一种情况如果找的轮换是如下形式,则要进行处理在计算次数:

                         2     1      3      1     3                    ---------->                    2     1     3              3     1        

                         1     3      1      3     2                                                       1      3     2              1     3

                     这组数据有个特点就是轮换之中包含着对换,直接计算交换次数是4次,但是我们可以把它拆成右边的两组,交换次数变为2+1=3次。显然右边的交换次数少,

                     是我们需要的。当遇到这种数据时,方法是找出轮换中对换的个数,然后总的次数减去对换的个数。在此例中有一个对换,就是4-1=3了。

源代码:

/*
ID: supersnow0622
PROG: sort3
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <string>
#include<algorithm>
#include<memory.h>
using namespace std;
int arr[1001],byOrder[1001],used[1001],judge[4];
int main() {
    ofstream fout ("sort3.out");
    ifstream fin ("sort3.in");
    int N,start,count;
    cin>>N;
    for(int i=0;i<N;i++)
    {
     cin>>arr[i];
     byOrder[i]=arr[i];
    }
    sort(byOrder,byOrder+N);
    int index,temp,sum=0;
    for(int i=0;i<N;i++)
     if(arr[i]==byOrder[i])
       used[i]=1;
    for(int i=0;i<N;i++)
    {
      memset(judge,0,sizeof(judge));
      if(!used[i]){
      start=arr[i];
      count=0;
      judge[start]=1;
      used[i]=1;
      index=i;
      while(byOrder[index]!=start)
      {
        sum++;
        temp=byOrder[index];
        int j;
        for(j=0;j<N;j++)
        {
          if(arr[j]==temp&&!used[j])
            {
              judge[temp]=1;
              used[j]=1;
              break;
            }
        }
        index=j;
        if(judge[byOrder[index]]==1)
          {
            memset(judge,0,sizeof(judge));
             judge[start]=1;
            count++;
          }
      }
       if(count!=1)
           sum=sum-count+1;
    }
    }
     cout<<sum;
    return 0;
}


       

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值