sort3解题报告 —— icedream61 博客园(转载请注明出处)
------------------------------------------------------------------------------------------------------------------------------------------------
【题目】
  给你N,而后给出N个数,每个数都是1~3中的一个。请问,要把这个数列升序排好,最少需要进行几次两两交换?
【数据范围】
  1<=N<=1000
【输入样例】
  9
  2
  2
  1
  3
  3
  3
  2
  3
  1
【输出样例】
  4
------------------------------------------------------------------------------------------------------------------------------------------------
【分析】
  模拟一遍最优策略,便可得出答案,具体做法如下:
    1、读入N,并读入N个数d[1]~d[N],定义最少所需交换次数s=0
    2、统计下1~3分别的个数,得到1的个数num[1]和1、2的总个数num[2]。此时,便可确定最终1~3的位置分别是:
      1: 1~num[1]
      2: num[1]+1~num[2]
      3: num[2]+1~N
    3、第一轮交换,使所有的1都到位:
      i=1~num[1],找!=1的位置,不存在则不妨令i==num[1]+1
      当i==num[1]+1则说明所有1均到位,本轮结束。否则,
      j=num[1]+1~num[2],找==1的位置,不存在则不妨令j==num[2]+1
      k=num[2]+1~N,找==1的位置,不存在则不妨令j==N+1
      能到这里说明需要交换一次,故而++S,
      对当前i,首先争取一步换到位(即d[i]==2与d[j]换,或者d[i]==3与d[k]换),如不可能则找一个合法的换便可,不可能出现没有合法的换的情况。
    4、第二轮交换,使所有的2都到位(3自然也就都到位了):
      i=num[1]+1~num[2],找!=2的位置,不存在则不妨令i==num[2]+1
      当i==num[2]+1则说明所有2均到位,本轮结束。否则,
      j=num[2]+1~N,找==2的位置,不存在则不妨令j==N+1
      能到这里说明需要交换一次,故而++S,
      交换d[i]与d[j]。
    5、至此,两轮交换完成,所得s即为最少所需交换次数。
------------------------------------------------------------------------------------------------------------------------------------------------
【总结】
  开始没有注意到随便交换并非最优,没考虑到的就是分析中第3步的情况:在第一轮中应当先争取一步到位,这样可以减少一次交换次数。
  本题还有个需要注意的地方(快排、二分等方法中也常出现这个问题),为了让下标不超出范围,要随时判断是否越界。

------------------------------------------------------------------------------------------------------------------------------------------------

【代码】

  1. /*
  2. ID: icedrea1
  3. PROB: sort3
  4. LANG: C++
  5. */
  6.  
  7. #include <iostream>
  8. #include <fstream>
  9. using namespace std;
  10.  
  11. int N,d[];
  12. int num[];
  13.  
  14. int main()
  15. {
  16. ifstream in("sort3.in");
  17. ofstream out("sort3.out");
  18.  
  19. in>>N;
  20. for(int i=;i<=N;++i) { in>>d[i]; ++num[d[i]]; }
  21. num[]+=num[];
  22.  
  23. // The situation of vector d:
  24. // 1: d[1]~d[num[1]]
  25. // 2: d[num[1]+1]~d[num[2]]
  26. // 3: d[num[2]+1]~d[N]
  27.  
  28. int s=;
  29. for(int i=,j=num[]+,k=num[]+;;)
  30. {
  31. while(i<=num[] && d[i]==) ++i;
  32. if(i==num[]+) break;
  33. while(j<=num[] && d[j]!=) ++j;
  34. while(k<=N && d[k]!=) ++k;
  35. ++s;
  36. if(d[i]== && j<=num[]) swap(d[i],d[j]); else if(d[i]== && k<=N) swap(d[i],d[k]); // 一步换到位更优
  37. else if(j<=num[]) swap(d[i],d[j]); else swap(d[i],d[k]); // 无法一步到位,那就换个合法的就行
  38. }
  39. for(int i=num[]+,j=num[]+;;)
  40. {
  41. while(i<=num[] && d[i]==) ++i;
  42. if(i==num[]+) break;
  43. while(j<=N && d[j]!=) ++j;
  44. swap(d[i],d[j]); ++s;
  45. }
  46.  
  47. out<<s<<endl;
  48.  
  49. in.close();
  50. out.close();
  51. return ;
  52. }

USACO Section2.1 Sorting a Three-Valued Sequence 解题报告的更多相关文章

  1. USACO Section 2.1 Sorting a Three-Valued Sequence 解题报告

    题目 题目描述 给N个整数,每个整数只能是1,2,或3.现在需要对这个整数序列进行从小到大排序,问最少需要进行几次交换.N(1 <= N <= 1000) 样例输入 9 2 2 1 3 3 ...

  2. timus 1175. Strange Sequence 解题报告

    1.题目描述: 1175. Strange Sequence Time limit: 1.0 secondMemory limit: 2 MB You have been asked to disco ...

  3. USACO Section 1.1 Your Ride Is Here 解题报告

    题目 问题描述 将字符串转变为数字,字母A对应的值为1,依次对应,字母Z对应的值为26.现在有一个字符串,将其中的每个字符转变为数字之后进行累乘,最终的结果对47求余数. 题目给你两个字符串,其中的字 ...

  4. LeetCode: Permutation Sequence 解题报告

    Permutation Sequence https://oj.leetcode.com/problems/permutation-sequence/ The set [1,2,3,…,n] cont ...

  5. LeetCode: Longest Consecutive Sequence 解题报告

    Longest Consecutive Sequence Given an unsorted array of integers, find the length of the longest con ...

  6. BZOJ 1367 [Baltic2004]sequence 解题报告

    BZOJ 1367 [Baltic2004]sequence Description 给定一个序列\(t_1,t_2,\dots,t_N\),求一个递增序列\(z_1<z_2<\dots& ...

  7. Winter-1-F Number Sequence 解题报告及测试数据

    Time Limit:1000MS     Memory Limit:32768KB Description ​A number sequence is defined as follows:f(1) ...

  8. 洛谷 P4597 序列sequence 解题报告

    P4597 序列sequence 题目背景 原题\(\tt{cf13c}\)数据加强版 题目描述 给定一个序列,每次操作可以把某个数\(+1\)或\(-1\).要求把序列变成非降数列.而且要求修改后的 ...

  9. gzhu 2013 Good Sequence 解题报告

    题目链接:(这个是内网的网址)  http://172.22.27.1/problem?pid=1013 Good Sequence Time Limit: 4000/2000 MS (Java/Ot ...

随机推荐

  1. GNU Nano编辑器

    ^表示 control建 ^X 退出 nano ^O 保存文件 ^R 插入其他文件内容至光标位置 ^W 查找字符串 ^Y 跳至前一屏 ^V 跳至后一屏 ^K 剪切光标所在行并保存到剪贴板,或剪切选中内 ...

  2. 《孵化Twitter》:Twitter创始人勾心斗角史,细节披露程度令人吃惊

    本书详细讲述twitter的发展史.感觉基本上是一部创始人从朋友变敌人,勾心斗角的历史.Twitter本身的产品发展反而相对比较简单. 书中披露了许多email.谈话.会议的细节,作者说这些是数百个小 ...

  3. java 使用hashmap一个键对应多值的方法

    背景:在你使用map对象时,你可能会有一个key,对应多个值的需求 实现: import java.util.ArrayList; import java.util.HashMap; import j ...

  4. HttpServerUtility 和 HttpUyility

    参考:msdn HttpServerUtility 提供用于处理 Web 请求的 Helper 方法. 2017/08/07            加密解码 这个类没有构造函数,所以不能直接new. ...

  5. 高亮代码 SyntaxHighlighter

    SyntaxHighlighter: http://alexgorbatchev.com/SyntaxHighlighter/download/ demo <!DOCTYPE html PUBL ...

  6. CSS 滤镜技巧与细节

    本文主要介绍 CSS 滤镜的不常用用法,希望能给读者带来一些干货! 注意:ie不兼容 本文所描述的滤镜,指的是 CSS3 出来后的滤镜,不是 IE 系列时代的滤镜,话不多说,直接开车,语法如下: { ...

  7. MFC项目依赖 BCG框架示例

    1.创建一个简单的MFC工程: 2.将BCG框架项目导入到新建的mfc解决方案中,例如将BCGCBPro\BCGCBPRO140.vcxproj添加到解决方案. 3.修改mfc项目属性,包含BCG框架 ...

  8. 漂亮提醒框js

    <script type="text/javascript"> var filename = "PICC_V2.1.3.0_新增功能操作手册.doc" ...

  9. Linux下使用指定网卡进行ping操作

    目录   1. 为什么要使用知道那个网卡ping操作   2. 使用指定网卡ping操作   3. 总结 1. 为什么要使用指定网卡ping操作 现在很多服务器都拥有双网卡甚至多网卡,有些是为了保持高 ...

  10. java从图片中识别文字

    package com.dream.common; import java.awt.image.BufferedImage; import java.io.File; import java.io.I ...