USACO Train 2.1.3 Sorting a Three-Valued Sequence(sort3)

这道题就是给出由123三个值的一个数字序列,然后让你把这个序列升序排序,求最小的交换次数。注意这里可以不是相邻交换。

刚开始一看题的时候,还以为t=a a=b b=t那种水题呢,然后发现不是水题。。

于是就想思路...既然是排序题,就先把他排序好了,然后就再对比一下。

比如说USACO上的样例数据:

排序前   排序后

(1)2 1
(2)2 1
(3)1 2
(4)3 2
(5)3 2
(6)3 3
(7)2 3
(8)3 3
(9)1 3

既然他要求的是最少次数,那么我们就不要移动已经在原位不用移动的数据,所以我们可以把在原位不用移动的数据删掉。这里的6和8是不用移动的数据。删掉后,然后变成了:

(1)2 1
(2)2 1
(3)1 2
(4)3 2
(5)3 2
(7)2 3
(9)1 3

这就出现可以两两交换的位置了,比如说第1号位置和第3号位置可以两两交换。我们把可以两两交换的位置定义为交叉相等。这个数据里面的第1号和第3号是交叉相等,第3号和第7号是交叉相等的,所以把他们两两交换就能回到原位了。两两交换只会交换一次,所以在这一步里面,把答案每交换一次+1,直到没有再能两两交换的位置了。然后就变成了:

(2)2 1
(5)3 2
(9)1 3

我们发现这里就剩下三组了,其实每一组数据筛选之后都会变成3的倍数组。想一想为什么。因为他这里面一共会出现3种数据(1,2,3),而会出现第一次筛选出现的在原位的情况,第二次筛选出现的互相换的情况,这次该出现三数据交换的情况了。为什么不会出现四个数据交换?因为他只有三个数据,你第四个数据哪里蹦出来的。。。既然剩下的都是三个数据交换,那么就不用再次寻找了,可以用剩余数据总数直接计算了。因为每一对三数据换会换两次(自己试试就知道了),所以这一次需要交换的次数为(剩余组数/3*2)。

既然思路理清了,就上代码把。。

解释一下,a是输入的数组,b是排序后的数组,c是是否被排除,没排除就是0,被排除就是1。

n是输入的数据总数,m是剩余的数据总数(会不断减少)。ans就是答案,就是交换的总次数。

/*
ID:aaabbbr1
LANG:C++
TASK:sort3
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int a[1002];
int b[1002];
bool c[1002];
int main()
{
	freopen("sort3.in","r",stdin);
	freopen("sort3.out","w",stdout);
	int n,m;
	scanf("%d",&n);
	m=n;//刚开始的时候,剩余数据数等于数据总数
	int ans=0;//答案要是0
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		b[i]=a[i];//b数组是用来排序的
	}
	sort(b+1,b+1+n);//排序b数组
	memset(c,0,sizeof(c));//c数组是用来标识是否被排除的
	for(int i=1;i<=n;i++)//枚举一个换的情况
	{
		if(a[i]==b[i])//如果数据在原位
		{
			m--;//剩余数据数-1
			c[i]=1;//排除数据
		}
	}
	for(int i=1;i<=n;i++)
	for(int j=1;j<i;j++)//这可以遍历任意不同的组合,穷举法,穷举两个换的情况	{
		if(a[i]==b[j]&&a[j]==b[i]&&c[i]!=1&&c[j]!=1)//意思是如果符合交叉相等并且两个都未被排除
		{
			m-=2;//数据剩余数减去2
			ans+=1;//答案+1,需要交换一次
			swap(a[i],a[j]);//这句好像没必要
			c[i]=1;//排除,否则出错
			c[j]=1;//同上
		}
	}
	ans+=m/3*2;//这是3个换的情况
	printf("%d\n",ans);
	fclose(stdin);
	fclose(stdout);
	return 0;
}
时间: 2024-08-12 04:33:06

USACO Train 2.1.3 Sorting a Three-Valued Sequence(sort3)的相关文章

【USACO】Sorting a Three-Valued Sequence(思路)

拼了老命用一种贪心的思想把它A了,但是代码写的太烂了,而且时间复杂度为 n ^ 2,我就不多说了,太烂了 之后上网找了一个规律,时间复杂度为 nlogn,而且思路很明确,又写了一遍 代码:(贪心) /* ID: 18906421 LANG: C++ PROG: sort3 */ #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std

【USACO 2009 JAN】地震造成的破坏Earthquake Damage(DFS)

题目描述 农夫John的农场遭受了一场地震.有一些牛棚遭到了损坏,但幸运地,所有牛棚间的路径都还能使用. FJ的农场有P(1 <= P <= 30,000)个牛棚,编号1..P,C(1 <= C <= 100,000)条双向路径连接这些牛棚,编号为1..C,路径i连接牛棚a_i和b_i (1 <= a_i<= P;1 <= b_i <= P),路径可能连接a_i到它自己,两个牛棚之间可能有多条路径.农庄在编号为1的牛棚.N (1 <= N <=

bzoj usaco 金组水题题解(1)

UPD:我真不是想骗访问量TAT..一开始没注意总长度写着写着网页崩了王仓(其实中午的时候就时常开始卡了= =)....损失了2h(幸好长一点的都单独开了一篇)....吓得赶紧分成两坨....TAT.............. —————————————————————————————————————————————————————————————————————————————— 写(被虐)了整整一个月b站上usaco的金组题...然而到现在总共只写了100道上下TAT(当然是按AC人数降序排

HDU1022 Train Problem I (栈)

栈+队列 1 #include<stdio.h> 2 #include<string.h> 3 #include<stack> 4 #include<queue> 5 using namespace std; 6 int main() 7 { 8 int n; 9 char a[11],b[11]; 10 stack<char>s; 11 queue<int>q; 12 while(scanf("%d",&

USACO抓牛catchcow (bfs)

这题是黄巨大出的比赛题. http://poj.org/problem?id=3278 Description Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤

USACO Mother&amp;#39;s Milk(bfs)

a=9MvljJDNdls&S=milk3">题目请点我 题解: 水杯倒水的问题非常经典,套路也是一样的,bfs找出全部状态. 这道题的关键在于每次都应该进行六次的倒水尝试,细心一点.PS:三维数组表示状态真的非常方便. 代码实现: /* ID: eashion LANG: C++ TASK: milk3 */ #include <iostream> #include <cstdio> #include <cstdlib> #include &l

UVA 12123 - Magnetic Train Tracks(计数问题)

题目链接:12123 - Magnetic Train Tracks 题意:给定n个点,求有几个锐角三角形. 思路:和UVA 11529是同类的题,枚举一个做原点,然后剩下点根据这个原点进行极角排序,然后利用two pointer去遍历一遍,找出角度小于90度的锐角,然后扣掉这些得到钝角三角形的个数,然后在用总情况去扣掉钝角就是锐角或直角 代码: #include <stdio.h> #include <string.h> #include <math.h> #incl

POJ 3270 Cow Sorting(置换群)

题目链接 题意 : N头牛,每个牛的坏脾气都有一个值,每个值都不相同,把这个值按照从小到大排序,如果两个值交换,那么会花掉这两个值之和的时间,让你花最少的时间将每个值从小到大排好序,求最小的总时间. 思路 : 这个在黑书上有写,就是置换群,248页有写.写的挺详细的.每个状态都可以分为若干个循环的乘积.对于任意循环 i ,设其长度为ki,则至少需要交换ki-1次,即每次让一个元素到达目标位置,而当第ki-1个元素到达目标以后显然第ki个也已经到达目标.第一个方法是让循环中最小的元素t参加所有的交

USACO翻译:USACO 2012 JAN三题(2)

USACO 2012 JAN(题目二) 一.题目概览 中文题目名称 叠干草 分干草 奶牛跑步 英文题目名称 stacking baleshare cowrun 可执行文件名 stacking baleshare cowrun 输入文件名 stacking.in baleshare.in cowrun.in 输出文件名 stacking.out baleshare.out cowrun.out 每个测试点时限 1秒 1秒 1秒 测试点数目 10 10 10 每个测试点分值 10 10 10 比较方