acm/icpc live archive 2481, world final 2002 problem h. silly sort

Your younger brother has an assignment and needs some help. His teacher gave him a sequence of numbers to be sorted in ascending order. During the sorting process, the places of two numbers can be interchanged. Each interchange has a cost, which is the sum of the two numbers involved.

You must write a program that determines the minimal cost to sort the sequence of numbers.

Input 

The input file contains several test cases. Each test case consists of two lines. The first line contains a single integer n (n >1), representing the number of items to be sorted. The second line contains n different integers (each positive and less than 1000), which are the numbers to be sorted.

The input is terminated by a zero on a line by itself.

Output 

For each test case, the output is a single line containing the test case number and the minimal cost of sorting the numbers in the test case.

Place a blank line after the output of each test case.

Sample Input 

3 
3 2 1 
4 
8 1 2 4 
5 
1 8 9 7 6 
6 
8 4 5 3 2 7 
0 

Sample Output 

Case 1: 4 

Case 2: 17 

Case 3: 41 

Case 4: 34 


黑书 247 页

把数据排序,分割成若干个群,在群里,每个置换操作恢复一个数字的位置。
恢复一个群有两种办法:
1。引入全局最小值到群里,用最小值每次置换恢复一个数字的位置;
2。不引入全局最小值,用群里最小值,每次置换恢复一个数字的位置。

#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <algorithm>

#define SZ_MAX 100000

int num [SZ_MAX];
int sorted [SZ_MAX];
int sz;
int globMin;

#define NUM_MAX 1010

void Sort () {
    static int cnt [1010];
    memset (cnt, 0, sizeof (cnt));
    for (int i=0; i<sz; ++i) {
        ++cnt [num [i]];
    }
    int ind = 0;
    for (int i=0; i<NUM_MAX; ++i) {
        while (cnt[i]--) {
            sorted [ind++] = i;
        }
    }
    assert (ind == sz);
#ifdef _DEBUG
    for (int i=0; i<sz; ++i) {
        printf ("%d%s", sorted[i], i==sz-1 ? "\n" : " ");
    }
#endif
}

int BinSearch (int n) {
    int lo = 0;
    int hi = sz - 1;
    while (lo < hi) {
        int mid = (lo + hi) / 2;
        if (sorted [mid] < n) {
            lo = mid + 1;
        } else {
            hi = mid;
        }
    }
    assert (sorted [lo] >= n);
    assert (lo == 0 || sorted [lo - 1] < n);
    return lo;
}

void Solve () {
    if (scanf ("%d", &sz) == EOF || !sz) {
        exit (0);
    }
    globMin = 100000;
    for (int i=0; i<sz; ++i) {
        scanf ("%d", &num[i]);
        globMin = std::min (globMin, num [i]);
    }
    Sort ();

    static bool marked [SZ_MAX];
    memset (marked, 0, sizeof (marked));

    int cost = 0;

    for (int i=0; i<sz; ++i) {
        if (marked [i] || sorted [i] == num [i]) {
            continue;
        }
        int k = i;
        int sum = 0;
        int troopMin = 100000;
        int troopSz = 0;
        do {
#ifdef _DEBUG
            printf ("i = %d, k = %d\n", i, k);
#endif
            troopMin = std::min (troopMin, sorted [k]);
            sum += sorted [k];
            assert (! marked [k]);
            marked [k] = true;
            ++troopSz;
            k = BinSearch (num [k]);
            while (k < sz && (sorted [k] == num [k] || marked [k]) && i != k) {
                ++k;
            }
            assert (k < sz);
        } while (k != i);

        cost += sum + std::min ((troopSz + 1) * globMin + troopMin, (troopSz - 2) * troopMin);
#ifdef _DEBUG
        printf ("cost = %d\n", cost);
#endif
    }

    static int cs = 0;
    printf ("Case %d: %d\n\n", ++cs, cost);
}

int main () {
    while (true) {
        Solve ();
    }
    return 0;
}




阅读更多
个人分类: ACM
想对作者说点什么? 我来说一句

2015 ACM-ICPC World Final 试题

2015年05月21日 2.09MB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭