排序的代价

【题目描述】

有一列数,要对其进行升序排序。排序只能通过交换来实现。每次交换,可以选择这列数中的任意两个,交换他们的位置,并且交换的代价为两个数的和。排序的总代价是排序过程中所有交换代价之和。现要求计算,对于给出的数列,要将其排成升序所需的最小代价。

【输入描述】

第一行输入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
*/
原文地址:https://www.cnblogs.com/Ackermann/p/5872964.html