ACM集训的第。。。诶~不知道第几题=.=
题目:
郭铮鹏认为排序是一种很频繁的计算任务,所以他考虑了一个简单的问题:现在最多只有三值的排序问题。一个实际的例子是,当我们给某项竞赛的优胜者按金银铜牌排序的时候。在这个任务中可能的值只有三种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
思路:
应使用贪心算法。
分析:先存入数组,然后记录有多少个1,多少个2,多少个3,然后记录应该是1的领地里不是1的个数,记录2的领地里3的个数,记录3的领地里2的个数
则我们要做的是把1的领地里非1的元素同后面两个区域里的1交换, 在1的领地里把2同 2的领地里的1 交换,把3同 3的领地里的1 进行交换 。
完了会出现2和3里面分别有3和2的情况,取2和3里的非自己人的最大数,同1里的为自己人数相加即为需要交换的最小次数。
即ans=x+max(y,z);
代码:
1 #include<iostream> 2 #include<cmath> 3 #include<cstring> 4 #define FOR(i,s,n) for(int i=s;i<n;i++) //因为我比较懒嘛,所以把for循环直接简化了,下面的三四个循环可以自行带入。╮(╯▽╰)╭ 5 using namespace std; 6 int main(){ 7 int x=0,y=0,z=0,n,b[3],ans=0; 8 memset(b,0,3); 9 scanf("%d",&n); 10 int a[n]; 11 FOR(i,0,n){ 12 scanf("%d",&a[i]); 13 b[a[i]-1]++; 14 } 15 FOR(i,0,b[0]){ 16 if(a[i]!=1)x++; 17 } 18 FOR(i,b[0],b[0]+b[1]){ 19 if(a[i]==3)y++; 20 } 21 FOR(i,b[0]+b[1],n){ 22 if(a[i]==2)z++; 23 } 24 printf("%d",x+max(y,z)); 25 }