[题目描述]
Sorting a Three-Valued Sequence
三值的排序
IOI'96 - Day 2
排序是一种很频繁的计算任务。现在考虑最多只有三值的排序问题。一个实际的例子是,当我们给某项竞赛的优胜者按金银铜牌序的时候。
在这个任务中可能的值只有三种1,2和3。我们用交换的方法把他排成升序的。
写一个程序计算出,给定的一个1,2,3组成的数字序列,排成升序所需的最少交换次数。
PROGRAM NAME: sort3
INPUT FORMAT
Line 1: |
N (1 <= N <= 1000) |
Lines 2-N+1: |
每行一个数字,共N行。(1..3) |
SAMPLE INPUT (file sort3.in)
9
2
2
1
3
3
3
2
3
1
OUTPUT FORMAT
共一行,一个数字。表示排成升序所需的最少交换次数。
SAMPLE OUTPUT (file sort3.out)
4
[解题思路]
由于需要排序的值只有1~3,所以可以边读入边基数排序,然后O(N)的预处理出一个数组t[i,j],i,j∈[1,3],表示在i应在的区间里的j的个数。
所以贪心的想法就是,先交换一次就能两两复原的数对,所以交换1中的2与2中的1,1中的3,与3中的1......这样,都只需交换一次。
而剩下的的在1中的2与1中的3都不能直接交换了,必须借助另一个区间的值,所以要交换两次,于是累计答案就行了。
[Code]
{
ID: zane2951
PROG: sort3
LANG: PASCAL
}
program sort3;
var
a:array[0..1111] of longint;
c:array[0..4] of longint;
t:array[0..4,0..4] of longint;
n,i,ans,ce:longint;
//-----------min-----------
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
//----------main-----------
begin
assign(input,'sort3.in'); reset(input);
assign(output,'sort3.out'); rewrite(output);
readln(n);
for i:=1 to n do begin readln(a[i]); inc(c[a[i]]); end;
for i:=1 to c[1] do inc(t[1,a[i]]);
for i:=c[1]+1 to c[1]+c[2] do inc(t[2,a[i]]);
for i:=c[1]+c[2]+1 to n do inc(t[3,a[i]]);
ans:=0;
//-------swap 1 and 2--------
ce:=min(t[1,2],t[2,1]);
ans:=ans+ce;
t[1,2]:=t[1,2]-ce; t[2,1]:=t[2,1]-ce;
//-------swap 1 and 3--------
ce:=min(t[1,3],t[3,1]);
ans:=ans+ce;
t[1,3]:=t[1,3]-ce; t[3,1]:=t[3,1]-ce;
//-------swap 2 and 3--------
ce:=min(t[2,3],t[3,2]);
ans:=ans+ce;
t[2,3]:=t[2,3]-ce; t[3,2]:=t[3,2]-ce;
//-------swap 1 and 2 and 3--------
ans:=ans+t[1,2]<<1+t[1,3]<<1;
writeln(ans);
close(input); close(output);
end.