POJ3270 置换群

给你一群牛逼的牛,每只牛有一个重量(姑且当成重量,或权值,whatever),you know,越重的牛必然越牛逼。初始时牛群无序排列,需要FJ去根据牛重排序,排序过程就是不停的交换任意两只牛的位置直至有序,移动两只牛的代价为两只牛的重量和。As you know,牛逼的牛移动起来比较费劲,FJ怎么才能花费最小的代价才能排好序呢? 上置换群:根据贪心策略,我们总是希望每次交换时那个最不牛逼的牛都参与,还是改口为“置换”吧,这样显的¥%…&*,就是不停的两两置换,置换过程会产生一个个的循环,这些产生的循环并在一起就构成了一个置换群(见任意一本《离散数学》),我们只需找到这个置换群的每个元素(循环)中的最不牛逼的牛,暂称为局部最不牛逼牛。然后根据greedy策略开始置换即可,直至这个循环内的所有元素有序。每个循环置换过程的花费为ans+(num-1)*inf,其中inf为当前循环中的最小值,num为置换次数。ans为循环内所有元素和,因为inf在ans已经被加一次,故要num-1;除此之外还有一种置换策略,引进外牛,即拿所有的牛中最不牛逼的牛,暂称为全局最不牛逼牛,参与这个循环的置换,这时可能也会产生最小代价置换排序,其值为:ans+(num-1)*least+2*(least+inf),least即为全局最不牛逼牛的重量,num为置换次数,ans为循环内所有牛的质量,易知刚开始要有一个牛i要跟least交换,暂时离开这个循环,然后最不牛逼牛进来参与置换,最后这个最不牛逼牛还是要离开这个循环的,所以i跟least交换两次,根据greedy策略,这个i必然要选局部最不牛逼牛。故而出现2*(least+inf),而least跟其余牛就只剩下了num-1次置换,总花费就是ans+(num-1)*least+2*(least+inf)。至于二者哪个花费最小,比较一下即可。今天面向对象一把: #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int sup=10010; int n; class cow { public: int id; int value; }; bool cmp(cow a,cow b) { return a.value<b.value; } class permutation { public: cow niu[sup]; permutation(){} void group(); ~permutation(){} }; void permutation::group() { int i; scanf("%d",&n); for(i=0;i<n;++i) { scanf("%d",&niu[i].value); niu[i].id=i; } sort(niu,niu+n,cmp); int inf,least=niu[0].value; int num,tmp,next,ans=0; for(i=0;i<n;++i) { if(niu[i].id!=-1) { num=1; inf=niu[i].value;//局部循环内最小 tmp=niu[i].id; niu[i].id=-1;//标记已访问过 while(tmp!=i) { ans+=niu[tmp].value; next=niu[tmp].id; niu[tmp].id=-1; tmp=next; num++; } ans+=(num-1)*inf>(num-1)*least+2*(least+inf)?(num-1)*least+2*(least+inf):(num-1)*inf; } } printf("%d/n",ans); } int main() { permutation pzjay; pzjay.group(); return 0; }

你可能感兴趣的:(Class,permutation)