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 }

 

posted @ 2016-06-30 15:11  meetviolet  Views(417)  Comments(0Edit  收藏  举报