排序是一种很频繁的计算任务.现在考虑最多只有三值的排序问题.一个实际的例子是,当我们给某 项竞赛的优胜者按金银铜牌序的时候. 在这个任务中可能的值只有三种 1,2 和 3.我们用交换的方法把他排成升序的. 写一个程序计算出,给定的一个 1,2,3 组成的数字序列,排成升序所需的最少交换次数.
输入格式:
Line 1: N (1 <= N <= 1000) Lines 2-N+1: 每行一个数字,共 N 行.(1…3)
输出格式:
共一行,一个数字.表示排成升序所需的最少交换次数.
输入样例1:
在这里给出一组输入。例如:
9
2
2
1
3
3
3
2
3
1
输出样例1:
共一行,一个数字.表示排成升序所需的最少交换次数.
4
输入样例2:
50
1
1
1
3
1
3
2
1
2
3
3
1
3
2
1
1
2
3
2
2
3
3
2
3
2
2
3
1
1
1
1
1
1
1
3
1
1
2
2
3
1
1
3
3
2
1
1
1
3
2
输出样例2:
18
输入样例3:
100
3
2
2
3
1
2
2
2
1
2
2
3
2
3
2
2
3
3
2
2
2
3
3
3
3
2
2
1
2
2
1
1
1
3
1
1
2
2
3
3
1
1
2
2
1
1
3
1
3
1
3
2
1
2
1
3
3
3
1
2
1
1
2
1
3
2
2
1
1
1
3
1
2
2
3
3
2
3
3
2
1
2
3
1
3
1
1
3
3
1
1
1
1
3
1
1
2
3
1
2
输出样例3:
37
【思路】
【源代码】
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int N;
cin >> N;
vector<int> List;
int length_I = 0;
int length_II = 0;
int length_III = 0;
int a = 0;
for (int i = 0; i < N; i++) // 储存原序列,并记录I、II、III段的长度;
{
cin >> a;
switch(a)
{
case 1: length_I++; break;
case 2: length_II++; break;
case 3: length_III++; break;
}
List.push_back(a);
}
int sum = 0;
for (int i = 0; i < length_I; i++) // 遍历I段,进行1次完全交换;
{
if (List[i] == 1) // I段有1,不交换; (可删)
{
continue;
}
else if (List[i] == 2) // I段有2, 进入II段寻找;
{
for (int j = length_I; j < (length_I+length_II); j++)
{
if (List[j] == 2) // I段有2,II段有2,不交换; (可删)
{
continue;
}
else if (List[j] == 1) // I段有2,II段有1,1次完全交换;
{
List[i] = 1;
List[j] = 2;
sum++;
break; // 1成功交换到I段;
}
else if (List[j] == 3) // I段有2,II段有3,不交换;
{
continue;
}
}
}
//1.可能I段余下2;
else if (List[i] == 3) // I段有3,进入III段寻找;
{
for (int k = (length_I+length_II); k < (length_I+length_II+length_III); k++)
{
if (List[k] == 3) // I段有3,III段有3,不交换;(可删)
{
continue;
}
else if (List[k] == 1) // I段有3,III有1,1次完全交换;
{
List[i] = 1;
List[k] = 3;
sum++;
break; // 1成功交换到I段;
}
else if (List[k] == 2) // I段有3,III段有2,不交换;
{
continue;
}
}
}
//2.可能I段余下3;
}
for (int j = length_I; j < (length_I+length_II); j++) // 遍历II段;
{
if (List[j]==2) // II段有2;(可删)
{
continue;
}
else if (List[j]==3) // II段有3,进入III段寻找;
{
for (int k = (length_I+length_II); k < (length_I+length_II+length_III); k++)
{
if (List[k]==3) // II段有3,III段有3,不交换;(可删)
{
continue;
}
else if (List[k]==2) // II段有3,III段有2,1次完全交换;
{
List[j] = 2;
List[k] = 3;
sum++;
break; // 2成功交换到II段;
}
}
}
}
// 余下的只能是两次交换;
for (int i = 0; i < length_I; i++)
{
int flag = 0;
if (List[i]==2) // I段2,II段3,III段1;
{
for (int j = length_I; j < (length_I+length_II); j++)
{
if (List[j]==3)
{
for (int k = (length_I+length_II); k < (length_I+length_II+length_III); k++)
{
if (List[k]==1)
{
List[i] = 1;
List[j] = 2;
List[k] = 3;
sum += 2;
flag = 1;// 成功交换
break;
}
}
}
if (flag == 1)
{
break;
}
}
}
else if (List[i]==3) // I段3,III段2,II段1;
{
for (int k = (length_I+length_II); k < (length_I+length_II+length_III); k++)
{
if (List[k] == 2)
{
for (int j = length_I; j < (length_I+length_II); j++)
{
if (List[j]==1)
{
List[i] = 1;
List[j] = 2;
List[k] = 3;
sum += 2;
flag = 1; // 成功交换
break;
}
}
}
if (flag == 1)
{
break;
}
}
}
}
cout << sum << endl;
return 0;
}