poj 3270 Cow Sorting

这个题是一道置换问题的题,是黑书上面的无聊的排序问题;根据群论知识我们可以分解为S个不想交的循环的乘积。例如:8 4 5 3 2 7,目标状态为2 3 4 5 7 8,

我们可以分解为两个循环的乘积,(8 2 7 ), ( 4 3 5 )。我们知道对两个循环分别进行完成交换,就可以完成任务;

对于任意一个循环i,设他的长度为ki,容易证明至少要循环ki - 1次,即每次让一个元素到达目标位置,而当第ki - 1元素到达目标以后显然第ki个也到达目标。我们知道每个循环至少要交换一次,要代价最小,因此我没每次拿最小的元素去交换,总的花费是sum(循环总值)+ ( cnt(循环个数) - 2 )*min(循环中的最小元素);

但是这种方法并不是最优的例如 1 6 7 8 9,可分解(1)(8 6 9 7)我们按上述方法算出的方法是 6 + 7 + 8 + 9 + (4 - 2)*6 = 42;

而实际是最小的值是6 + 7 + 8 + 9 + 6 + (4 + 1 )*1 = 41;

这是因为我们借助的循环以外的数和他们交换,我们让1与6进行交换那么1就进入了循环(6 1 7 8 9 )这样在进行原先的方法进行计算;

 cost = min( sum(循环总和) + MIN(循环中最小值)*( cnt(循环个数) - 2 ), sum + Min(全部元素最小值)*(cnt+1) + MIN  );

View Code
#include<iostream>

 #include<cstdio>

 #include<cstdlib>

 #include<algorithm>

 #include<cmath>

 #include<queue>

 #include<set>

 #include<map>

 #include<cstring>

 #include<vector>

 #include<string>

 #define LL long long

 using namespace std;

 class Node

 {

 public:

       int num,place;    

 }node[10024];

 bool cmp1( Node a , Node b )

 {

     return a.num < b.num;    

 }

 int Solve( int n ,int Min )

 {

     int sum = 0;

     bool visit[10024] = {0};

     for( int i = 0 ; i < n ; i ++ )

     {

          if( !visit[i] )

          {

              int s = node[i].num,cnt=1,m = node[i].place,MIN = node[i].num ;

              while( m!= i )

              {

                 visit[m] = true;

                 s += node[m].num;

                 cnt++;

                 if( node[m].num < MIN ) MIN = node[m].num;

                 m = node[m].place;                

              }

              sum += min( s + MIN*( cnt - 2 ), s + Min*(cnt+1) + MIN  );

          }    

     }

     return sum;    

 }

 int main(  )

 {

      int n;

      while( scanf( "%d",&n )==1 )

      {

           int Min = 0x7fffffff;

           for( int i = 0 ; i < n ; i ++ )

           {

               scanf( "%d",&node[i].num );

               node[i].place = i; 

               Min = min( node[i].num , Min );         

           }    

           sort( node , node + n , cmp1 );

           printf( "%d\n",Solve( n , Min ) );    

      }

     //system( "pause" );

     return 0;

 }

 

你可能感兴趣的:(sort)