USACO Section2.1 Sorting a Three-Valued Sequence 解题报告
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步的情况:在第一轮中应当先争取一步到位,这样可以减少一次交换次数。
本题还有个需要注意的地方(快排、二分等方法中也常出现这个问题),为了让下标不超出范围,要随时判断是否越界。
------------------------------------------------------------------------------------------------------------------------------------------------
【代码】
/*
ID: icedrea1
PROB: sort3
LANG: C++
*/ #include <iostream>
#include <fstream>
using namespace std; int N,d[];
int num[]; int main()
{
ifstream in("sort3.in");
ofstream out("sort3.out"); in>>N;
for(int i=;i<=N;++i) { in>>d[i]; ++num[d[i]]; }
num[]+=num[]; // The situation of vector d:
// 1: d[1]~d[num[1]]
// 2: d[num[1]+1]~d[num[2]]
// 3: d[num[2]+1]~d[N] int s=;
for(int i=,j=num[]+,k=num[]+;;)
{
while(i<=num[] && d[i]==) ++i;
if(i==num[]+) break;
while(j<=num[] && d[j]!=) ++j;
while(k<=N && d[k]!=) ++k;
++s;
if(d[i]== && j<=num[]) swap(d[i],d[j]); else if(d[i]== && k<=N) swap(d[i],d[k]); // 一步换到位更优
else if(j<=num[]) swap(d[i],d[j]); else swap(d[i],d[k]); // 无法一步到位,那就换个合法的就行
}
for(int i=num[]+,j=num[]+;;)
{
while(i<=num[] && d[i]==) ++i;
if(i==num[]+) break;
while(j<=N && d[j]!=) ++j;
swap(d[i],d[j]); ++s;
} out<<s<<endl; in.close();
out.close();
return ;
}
USACO Section2.1 Sorting a Three-Valued Sequence 解题报告的更多相关文章
- USACO Section 2.1 Sorting a Three-Valued Sequence 解题报告
题目 题目描述 给N个整数,每个整数只能是1,2,或3.现在需要对这个整数序列进行从小到大排序,问最少需要进行几次交换.N(1 <= N <= 1000) 样例输入 9 2 2 1 3 3 ...
- timus 1175. Strange Sequence 解题报告
1.题目描述: 1175. Strange Sequence Time limit: 1.0 secondMemory limit: 2 MB You have been asked to disco ...
- USACO Section 1.1 Your Ride Is Here 解题报告
题目 问题描述 将字符串转变为数字,字母A对应的值为1,依次对应,字母Z对应的值为26.现在有一个字符串,将其中的每个字符转变为数字之后进行累乘,最终的结果对47求余数. 题目给你两个字符串,其中的字 ...
- LeetCode: Permutation Sequence 解题报告
Permutation Sequence https://oj.leetcode.com/problems/permutation-sequence/ The set [1,2,3,…,n] cont ...
- LeetCode: Longest Consecutive Sequence 解题报告
Longest Consecutive Sequence Given an unsorted array of integers, find the length of the longest con ...
- BZOJ 1367 [Baltic2004]sequence 解题报告
BZOJ 1367 [Baltic2004]sequence Description 给定一个序列\(t_1,t_2,\dots,t_N\),求一个递增序列\(z_1<z_2<\dots& ...
- Winter-1-F Number Sequence 解题报告及测试数据
Time Limit:1000MS Memory Limit:32768KB Description A number sequence is defined as follows:f(1) ...
- 洛谷 P4597 序列sequence 解题报告
P4597 序列sequence 题目背景 原题\(\tt{cf13c}\)数据加强版 题目描述 给定一个序列,每次操作可以把某个数\(+1\)或\(-1\).要求把序列变成非降数列.而且要求修改后的 ...
- gzhu 2013 Good Sequence 解题报告
题目链接:(这个是内网的网址) http://172.22.27.1/problem?pid=1013 Good Sequence Time Limit: 4000/2000 MS (Java/Ot ...
随机推荐
- 基数排序C#界面版
第一步:生成数据 第二步:读取数据 第三步:创建队列 第四步:入队分配 第五步:出队收集重复第四步与第五步,直到出队入队各四次,完成基数排序:如下:4次入队结束后如下:最后一次出队:基数排序完成.. ...
- 【BZOJ3506】[CQOI2014] 排序机械臂(Splay)
点此看题面 大致题意: 给你\(n\)个数.第一次找到最小值所在位置\(P_1\),翻转\([1,P_1]\),第二次找到剩余数中最小值所在位置\(P_2\),翻转\([2,P_2]\),以此类推.求 ...
- nginx缓存批量清除
研究了一段时间的缓存清除,说说了解的三种方式吧. 1. 原始的只增加缓存模块的,根据访问的路径一条条清除. 根据此方式要进行批量清除的话,必须在设定的缓存目录下通过自己写的程序来读取ng ...
- 剑指offer49 把字符串转换成整数
这个代码会报错 class Solution { public: ,kinvalid}; int now_status = kvalid; int StrToInt(string str) { now ...
- python剑指offer数组中出现次数超过一半的数字
题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...
- linq 和lambda查询
EF 查询的两种 写法. linq 方法 或者 lambda方法 其中 ,只有tolist()的时候,才会真正的 在数据库中执行. 如果没有 tolist 方法,那么province1是 iqueab ...
- Java 压缩文件夹工具类(包含解压)
依赖jar <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons ...
- 修改SVN的地址
方法 1:右键在工作复本的根目录上右键->TortoiseSVN->重新定位 (Relocate),然后修改URL就可以了,但最好先备份一下,据说这样的操作有一定的危险性(至今我没有发现) ...
- multi-view datasets
http://rll.berkeley.edu/2014_ICRA_dataset/ http://rgbd-dataset.cs.washington.edu/dataset/
- 《阿里巴巴Java开发手册》阅读笔记
1.抽象类命名使用 Abstract 或 Base 开头: 异常类命名使用 Exception 结尾: 测试类命名以它要测试的类的名称开始,以 Test 结尾. 2.POJO 类中布尔类型的变量,都不 ...