USACO Sorting A Three-Valued Sequence (sort3)
来源:互联网 发布:算法怎么入门 编辑:程序博客网 时间:2024/05/17 08:44
我的思路是:记录下1,2,3的个数one, two, three,在前one个数里查,查到不是1的就从后面找到1进行swap。如果在前one个位置里找到2,就从two的带状位置里找1;如果在前one个数里找到3,就从three的带状位置里找1
等前one个数全整理为1,就在two的带状位置里找3,进行swap。
/*ID: wangxin12PROG: sort3LANG: C++*/#include <iostream>#include <fstream>#include <vector>#include <math.h>#include <string>using namespace std;int data[1005];int N;int one, two, three;int swap_times = 0;void swap(int data[1005], int & first, int second) {int temp = data[first];data[first] = data[second];data[second] = temp;swap_times++;}bool find(int data[1005], int start, int end, int target, int index) {for(int k = start; k <= end; k++) {if(data[k] == target) {swap(data, index, k);return true;}}return false;}int main() {ifstream fin("sort3.in");fin>>N;for(int i = 0; i < N; i++) {fin>>data[i];if(data[i] == 1) one++;if(data[i] == 2) two++;if(data[i] == 3) three++;}fin.close();int k = 0;//先把1给理到最前面for(k = 0; k < one; k++) {if( data[k] == 2) { //先找two位置里的1bool flag = find(data, one, one + two - 1, 1, k);//如果失败,找three位置里的1if(!flag) flag = find(data, one + two, one + two + three - 1, 1, k);}if( data[k] == 3) { //先找three位置里的1bool flag = find(data, one + two, one + two + three - 1, 1, k);//如果失败,找two位置里的1if(!flag) flag = find(data, one, one + two - 1, 1, k);}}//前one个1理顺了,理two位置里的3for(k = one; k < one + two; k++) {if( data[k] == 3) { bool flag = find(data, one + two, one + two + three - 1, 3, k);}}//Outputofstream fout("sort3.out");fout<<swap_times<<endl;fout.close(); return 0;}
根据NOCOW,有以下多种思路:
Way1
用l[i]记录i(1,2,3)出现的个数。排序后一定是l[1]个1,l[2]个2,l[3]个3这3段。
sn[i,j]记录在第i段中的j的个数。第i段中的j和第j段中的i交换,两个元素交换,只需要一次。所以取sn[i,j]和sn[j,i]中的较小数s,累加到总交换数中。
这样交换后,剩下的肯定是3段同时交换,最少需要2次。我们只需累加(sn[1,2]+sn[1,3])×2即可。
Way2
首先读入所有数,然后看原本的位置是“1”的里面有几个不是1,如果那几个不是1的数字在它原应该呆的位置中找到1的话就直接换,如果找不到就在另一堆中找。
比如说3 1 2三个数,第一个位置原应该是1,但是是3,那么就在原应该是3的位置中找1,但是是2,那么就在另一堆找,找到了1,那么把3跟1换一下,直到1全部到达自己的位置。然后在原应该是2的位置中找,如果碰到3就应该换一次,就这样找完就行了。
for i:=1 to n do
begin
readln(a[i]);
if a[i]=1 then inc(s[1,2])
else
if a[i]=2 then inc(s[2,2]);
end;
s[2,1]:=s[1,2]+1;
s[2,2]:=s[2,2]+s[2,1]-1;
s[3,1]:=s[2,2]+1;
这段代码是记录位置的,s[x,1]是x的初始位置,s[x,2]是x的终点位置。
记录好位置之后就按照上面的流程去找就好了,实现起来应该是很简单的。
Way3
这是极其诡异的做法: 只要类似与方法二,记录下本是N的位置却不是N的个数A[N],表示N这个数有多少个不在自己的位置上。
然后,开一个数组B,存储排序后的序列。每次比较原数列Data[i]和B[i],如果不相等,则dec(A[data[i]]),dec(A[b[i]]),inc(Total)。
本来只想着尝试这样的方法,没想到交上去后就AC了。莫名……只是求最小次数的问题这样可以AC……
Way4
O(n)预处理,O(1)计算(注:数字i该在的位置即排序后数字i所在的位置区间)。d[i,j]表示排序后数字i该在的位置中含有的数字j的个数。
那么,ans:=d[2,1]+d[3,1]+d[2,3]+max(0,d[1,3]-d[3,1])。
原理很简单,首先要把所有的1交换到最前面:用的次数是d[2,1]+d[3,1]。然后把所有的3交换到最后,这些3共两部分:一部分是在2该在的位置中的,这些需要d[2,3]次交换;另一部分是在1该在的位置中的,这些3中有一些是通过处理1已经回来了,还有一些可能在处理1的时候交换到了2该在的位置,就需要再交换一下。这部分交换总数是max(0,d[1,3]-d[3,1])。
我用的是这个方式的变形:ans:=d[1,2]+d[1,3]+max(d[2,3],d[3,2]);
处理解释:d[1,2]+d[1,3]是所有占据1位的2和3的数量,也就是不在正确位置的 1的数量(d[2,1]+d[3,1]),这两个加和是相同的。第一步求这个和,也就是让所有1归位。
此操作之后,存在两种情况。
一:原序列中不存在三值互换的现象,那么d[2,3]与d[3,2]应该是相同的。max算子不起作用。
二:原序列中存在三值互换的现象。可知,d[2,3]与d[3,2]中必有一个不变,而另一个在增大,且增大的量在数值上等于原三值交换的次数。就是例如上段文字所说:这些3中还有一些可能在处理1的时候交换到了2该在的位置,这时增加的就是d[2,3],而d[3,2]不变。由于交换是相对的,变化后的d'[2,3]与d'[3,2]必相等,又由于其中有一个值没有变动,所以该值也就等于原d[2,3]与d[3,2]中的最大值。
然后取这个最大值就可以让 2 3 同时归位。问题得解。
补充一点
我们用a[i,j]表示在i的位置上j的个数,比如a[2,1]=5就表示排好序后,上面应该是2,但现在被1占领的位置数是5。先贪心到不能两值内部交换。
那么操作之后不会存在a[2,1]>0和a[2,3]>0同时成立的现象。
反证法:比如交换之后a[2,1]>0,且a[2,3]>0则在1的位置上只能有3(1和2能内部相抵的已经全部抵消了),3的位置上只能有1(同理),那么1和3又可以内部交换了,与假设矛盾。得证。
还有最后3值交换是乘2,而不是乘3。
- USACO Sorting A Three-Valued Sequence (sort3)
- USACO 2.1 Sorting A Three-Valued Sequence (sort3)
- USACO2.1.3 Sorting A Three-Valued Sequence (sort3)
- USACO2.1.3 Sorting A Three-Valued Sequence (sort3)
- usaco training-Sorting a Three-Valued Sequence
- usaco: Sorting a Three-Valued Sequence
- usaco Sorting a Three-Valued Sequence
- USACO-Sorting a Three-Valued Sequence
- USACO Sorting a Three-Valued Sequence
- USACO 2.1 Sorting a Three-Valued Sequence
- USACO 2.1 Sorting a Three-Valued Sequence
- USACO--2.1Sorting a Three-Valued Sequence
- USACO 2.1 Sorting A Three-Valued Sequence
- USACO [2.1] Sorting a Three-Valued Sequence
- USACO 2.1-Sorting a Three-Valued Sequence
- USACO 2.1 Sorting a Three-Valued Sequence
- 【USACO】【贪心】Sorting a Three-Valued Sequence
- USACO Sorting a Three-Valued Sequence
- 【shell脚本学习】2.linux shell变量
- 给VC应用程序换皮肤的几种方法
- 回顾2006编辑的人工智能科学,现在已有更新充实(2012-06-25 22:12:29)
- Linux中的EAGAIN含义
- Linux平台代码覆盖率测试工具GCOV的前端工具LCOV简介
- USACO Sorting A Three-Valued Sequence (sort3)
- C#为什么多线程控制winform需要用委托?
- Android开发——NDK开发入门(转载)
- android listview notifyDataSetChange(),不起作用的可能原因
- 十年学会编程
- listview异步加载图片(深度优化)(转载)
- redis的事件框架
- 做android版水果忍者有感
- 如何导入导出MySQL数据库----*.sql文件操作