【题目描述】
有一列数,要对其进行升序排序。排序只能通过交换来实现。每次交换,可以选择这列数中的任意两个,交换他们的位置,并且交换的代价为两个数的和。排序的总代价是排序过程中所有交换代价之和。现要求计算,对于给出的数列,要将其排成升序所需的最小代价。
【输入描述】
第一行输入1个数n,表示这列数共有n(n <= 1000)个数组成;
第二行输入n个互不相同的整数(都是小于1000的正整数),表示这列数。
输入可能包含多组测试数据(少于50组),对于每个输入数据均需要给出对应的输出。
【输出描述】
对于每组输入数据,输出最小代价。
输出格式为“Case t: min”,其中t为数据的编号(从1开始编号),min为这个数据的最小代价。
【样例输入】
3
3 2 1
4
8 1 2 4
【样例输出】
Case 1: 4
Case 2: 17
源代码: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,Ans,Min,Number; bool f[1001]; struct Node { int S,To; }i[1001]; bool Rule(Node t1,Node t2) { return t1.S<t2.S; } void Clear() //初始化。 { Ans=0; Min=1000000000; memset(f,0,sizeof(f)); } int main() { while (scanf("%d",&n)!=EOF) { Clear(); for (int a=1;a<=n;a++) { scanf("%d",&i[a].S); Min=min(Min,i[a].S); i[a].To=a; } sort(i+1,i+1+n,Rule); for (int a=1;a<=n;a++) if (!f[a]) { int Sum=0,Num=0,T=1000000000,t=a; while (!f[t]) { T=min(T,i[t].S); Sum+=i[t].S; Num++; f[t]=true; t=i[t].To; } Ans+=Sum+min((Num-2)*T,(Num+1)*Min+T); } if (!Ans) break; printf("Case %d: %d ",++Number,Ans); } return 0; } /* 置换群,然而太高深了看不懂。 题解博客:http://www.cnblogs.com/wmrv587/p/3530506.html */