Sorting is one of the most frequently performed computational tasks. Consider the special sorting problem in which the records to be sorted have at most three different key values. This happens for instance when we sort medalists of a competition according to medal value, that is, gold medalists come first, followed by silver, and bronze medalists come last.
In this task the possible key values are the integers 1, 2 and 3. The required sorting order is non-decreasing. However, sorting has to be accomplished by a sequence of exchange operations. An exchange operation, defined by two position numbers p and q, exchanges the elements in positions p and q.
You are given a sequence of key values. Write a program that computes the minimal number of exchange operations that are necessary to make the sequence sorted.
PROGRAM NAME: sort3
INPUT FORMAT
Line 1: | N (1 <= N <= 1000), the number of records to be sorted |
Lines 2-N+1: | A single integer from the set {1, 2, 3} |
SAMPLE INPUT (file sort3.in)
9 2 2 1 3 3 3 2 3 1
OUTPUT FORMAT
A single line containing the number of exchanges required
SAMPLE OUTPUT (file sort3.out)
4
一道贪心算法的题。
先求出1, 2, 3的个数,分别为num[1], num[2], num[3]。这样我们就知道,排完序过后,1 ~ num[1]区间应全部为1, num[1] + 1 ~ num[2]区间应全部为2, num[2] + 1 ~ num[3]区间应全部为3。这里分别称这三个区间为区间1,区间2,区间3。
接下来,我们尽可能多地将区间1中的2和区间2中的1交换,直到区间1中没有2了或者区间2中没有1了。对区间1和区间3,区间2和区间3重复上面的操作。这样我们保证最多的1,2,3可以只经过一次交换就回到它应该在的位置。这是本题的贪心算法。
而剩下来的那些残留在不属于它的区间的1,2,3应该像下面这样:2在区间1,1在区间3,3在区间2(这是一种排列情况,举个例子)。但由于此时我们区间2里以及没有1了,区间3里已经没有2了,区间1里也没有3了,所以只好用两次交换操作把它们换回到他们的位置。
/*
ID: traysen1
TASK: sort3
LANG: C++
*/
#include <bits/stdc++.h>
using namespace std;
struct Interval {
int a, b, c; // Respectively represents 1, 2, and 3 in that interval;
}itv[5];
int N;
int records[1005], num[5], sum[5];
int main() {
ifstream fin("sort3.in");
fin >> N;
for (int i = 1; i <= N; i++) {
fin >> records[i];
if (records[i] == 1) num[1]++;
if (records[i] == 2) num[2]++;
if (records[i] == 3) num[3]++;
}
fin.close();
//Initialization
for (int n = 1; n <= 3; n++) sum[n] = sum[n - 1] + num[n];
for (int i = 1; i <= 3; i++) itv[i].a = 0, itv[i].b = 0, itv[i].c = 0;
for (int n = 1; n <= 3; n++) // For interval
for (int i = sum[n - 1] + 1; i <= sum[n]; i++) {
if (records[i] == 1) itv[n].a++;
if (records[i] == 2) itv[n].b++;
if (records[i] == 3) itv[n].c++;
}
int cnt = 0, total = 0;
//Swich 2 in itv[1] with 1 in itv[2]
cnt = min(itv[1].b, itv[2].a);
itv[1].b -= cnt, itv[2].a -= cnt;
total += cnt;
//Swich 3 in itv[1] with 1 in itv[3]
cnt = min(itv[1].c, itv[3].a);
itv[1].c -= cnt, itv[3].a -= cnt;
total += cnt;
//Swich 2 in itv[3] with 3 in itv[2]
cnt = min(itv[3].b, itv[2].c);
itv[3].b -= cnt, itv[2].c -= cnt;
total += cnt;
cnt = itv[2].a + itv[3].a;
total += cnt * 2;
ofstream fout("sort3.out");
fout << total << endl;
fout.close();
return 0;
}