2021-01-07 USACO Sorting a Three-Valued Sequence

Sorting is one of the most frequently performed computational tasks. Consider the special sorting problem in which the records to be sorted have at most three different key values. This happens for instance when we sort medalists of a competition according to medal value, that is, gold medalists come first, followed by silver, and bronze medalists come last.

In this task the possible key values are the integers 1, 2 and 3. The required sorting order is non-decreasing. However, sorting has to be accomplished by a sequence of exchange operations. An exchange operation, defined by two position numbers p and q, exchanges the elements in positions p and q.

You are given a sequence of key values. Write a program that computes the minimal number of exchange operations that are necessary to make the sequence sorted.

PROGRAM NAME: sort3

INPUT FORMAT

Line 1:N (1 <= N <= 1000), the number of records to be sorted
Lines 2-N+1:A single integer from the set {1, 2, 3}

SAMPLE INPUT (file sort3.in)

9
2
2
1
3
3
3
2
3
1

OUTPUT FORMAT

A single line containing the number of exchanges required

SAMPLE OUTPUT (file sort3.out)

4

一道贪心算法的题。

先求出1, 2, 3的个数,分别为num[1], num[2], num[3]。这样我们就知道,排完序过后,1 ~ num[1]区间应全部为1, num[1] + 1 ~ num[2]区间应全部为2, num[2] + 1 ~ num[3]区间应全部为3。这里分别称这三个区间为区间1,区间2,区间3。

接下来,我们尽可能多地将区间1中的2和区间2中的1交换,直到区间1中没有2了或者区间2中没有1了。对区间1和区间3,区间2和区间3重复上面的操作。这样我们保证最多的1,2,3可以只经过一次交换就回到它应该在的位置。这是本题的贪心算法。

而剩下来的那些残留在不属于它的区间的1,2,3应该像下面这样:2在区间1,1在区间3,3在区间2(这是一种排列情况,举个例子)。但由于此时我们区间2里以及没有1了,区间3里已经没有2了,区间1里也没有3了,所以只好用两次交换操作把它们换回到他们的位置。

/*
ID: traysen1
TASK: sort3
LANG: C++
*/
#include <bits/stdc++.h>
using namespace std;

struct Interval {
	int a, b, c; // Respectively represents 1, 2, and 3 in that interval;
}itv[5];
int N;
int records[1005], num[5], sum[5];

int main() {
	ifstream fin("sort3.in");
	fin >> N;
	for (int i = 1; i <= N; i++) {
		fin >> records[i];
		
		if (records[i] == 1) num[1]++;
		if (records[i] == 2) num[2]++;
		if (records[i] == 3) num[3]++;
	}
	fin.close();
	
	//Initialization
	for (int n = 1; n <= 3; n++) sum[n] = sum[n - 1] + num[n];
	for (int i = 1; i <= 3; i++) itv[i].a = 0, itv[i].b = 0, itv[i].c = 0;
	
	for (int n = 1; n <= 3; n++) // For interval
		for (int i = sum[n - 1] + 1; i <= sum[n]; i++) {
			if (records[i] == 1) itv[n].a++;
			if (records[i] == 2) itv[n].b++;
			if (records[i] == 3) itv[n].c++;
		}
	
	int cnt = 0, total = 0;
	//Swich 2 in itv[1] with 1 in itv[2]
	cnt = min(itv[1].b, itv[2].a);
	itv[1].b -= cnt, itv[2].a -= cnt;
	total += cnt;
	
	//Swich 3 in itv[1] with 1 in itv[3]
	cnt = min(itv[1].c, itv[3].a);
	itv[1].c -= cnt, itv[3].a -= cnt;
	total += cnt;
	
	//Swich 2 in itv[3] with 3 in itv[2]
	cnt = min(itv[3].b, itv[2].c);
	itv[3].b -= cnt, itv[2].c -= cnt;
	total += cnt;
	
	cnt = itv[2].a + itv[3].a;
	total += cnt * 2;
	
	ofstream fout("sort3.out");
	fout << total << endl;
	fout.close();
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值