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;
 }
 
posted @ 2012-09-10 20:01  wutaoKeen  阅读(120)  评论(0编辑  收藏  举报