南邮 OJ 1736 排序问题

排序问题

时间限制(普通/Java) :  1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 37            测试通过 : 18 

比赛描述

排序是一种很频繁的计算任务。现在考虑最多只有三值的排序问题。一个实际的例子是,当我们给某项竞赛的优胜者按金银铜牌排序的时候。在这个任务中可能的值只有三种1,2和3。我们用交换的方法把他排成升序的。

写一个程序计算出,给定的一个1,2,3组成的数字序列,排成升序所需的最少交换次数。



输入

多组数据

第一行:

奖牌个数N (1 <= N <= 1000)

第 2行到第N+1行:

每行一个数字,表示奖牌。共N行。(1..3)

输出

共一行,一个数字。表示排成升序所需的最少交换次数。

样例输入

9
2
2
1
3
3
3
2
3
1

样例输出

4

提示

undefined

题目来源

ym





// 设 cAB 为在A位置上的B的数目,则答案为:
// c21 + c31 + (c21 > c12 ? c23 + c21 - c12 : c32 + c12 - c21)
// 或者 c12 + c13 + max(c23,c32)


// 1-1、2-2、3-3的不交换(一轮换),1-2和2-1,1-3和3-1,2-3和3-2配对成二轮换,
// 剩下的形成1-2-3或1-3-2的三轮换。最后的交换次数是二轮换的数量加上三轮换的数量乘以二。
// 用公式表示的话就是:
// min(c12,c21) + min(c13,c31) + min(c23,c32) + |c12 - c21| * 2


#include<iostream>
using namespace std;

#define MAX_N 1001
int a[MAX_N];

int main(){
	int n, i, count1, count2;
	int c12, c13, c21, c23, c31, c32;
	while(scanf("%d", &n) == 1){
		count1 = count2 = 0;
		c12 = c13 = c21 = c23 = c31 = c32 = 0;
		for(i = 0; i < n; ++i){
			scanf("%d", a + i);
			if(a[i] == 1){
				count1++;
			}else if(a[i] == 2){
				count2++;
			}
		}
		for(i = 0; i < count1; ++i){
			if(a[i] == 2){
				c12++;
			}else if(a[i] == 3){
				c13++;
			}
		}
		for(i = count1; i < count1 + count2; ++i){
			if(a[i] == 1){
				c21++;
			}else if(a[i] == 3){
				c23++;
			}
		}
		for(i = count1 + count2; i < n; ++i){
			if(a[i] == 1){
				c31++;
			}else if(a[i] == 2){
				c32++;
			}
		}
		int temp = c12 - c21;
		if(temp < 0){
			temp = -temp;
		}
		printf("%d\n",  min(c12,c21) + min(c13,c31) + min(c23,c32) + temp * 2);
	}
}


你可能感兴趣的:(ACM,排序问题,南邮OJ)