pat(甲)1067(贪心+哨兵)

1067 Sort with Swap(0, i) (25 分)

Given any permutation of the numbers {0, 1, 2,..., N−1}, it is easy to sort them in increasing order. But what if Swap(0, *) is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the following way:

Swap(0, 1) => {4, 1, 2, 0, 3}
Swap(0, 3) => {4, 1, 2, 3, 0}
Swap(0, 4) => {0, 1, 2, 3, 4}

Now you are asked to find the minimum number of swaps need to sort the given permutation of the first N nonnegative integers.

Input Specification:

Each input file contains one test case, which gives a positive N (≤10​5​​) followed by a permutation sequence of {0, 1, ..., N−1}. All the numbers in a line are separated by a space.

Output Specification:

For each case, simply print in a line the minimum number of swaps need to sort the given permutation.

Sample Input:

10
3 5 7 2 6 4 9 0 8 1

Sample Output:

9

 

心得:题意是给出一段序列,用每次让0和其他数字交换位置的方法使序列变成非第减序列,求交换的次数。

哨兵的使用:本题中0作为排序交换的哨兵,通过交换实现序列有序。

实现方法 :1、用数组记录每个数所在的位置,然后交换a[0],和a[a[0]],让0原来在的位置上的数字归位。

直到0回到0的位置上。

2、交换后的序列有两种请况,一是每个位置对应相应的点,即排好序了;二是还有的位置没有交换,则以0位哨兵重复1的操作。

 

#include<iostream>
using namespace std;
int a[100100];
void sp(int x,int y)
{
	int tp=a[x];
	a[x]=a[y];
	a[y]=tp;
}
int main(void)
{
	int n,i,t;
	scanf("%d",&n);
	for(i=0;i<n;i++)
	{
		scanf("%d",&t);
		a[t]=i;
	}
	int cnt=0;
	for(i=0;i<n;i++)
	{
		while(a[0]!=0)
		{
			sp(a[0],a[a[0]]);
			cnt++;
		}
		if(a[i]!=i) 
		{
			sp(a[0],a[i]);
			cnt++;
		}
	}
	printf("%d\n",cnt);
	return 0;
}

参考文章:https://www.liuchuo.net/archives/2301

### 关于PAT乙级1120题的C++解法 以下是针对PAT乙级1120题的一个可能的C++实现方法。此题的核心在于处理输入数据并按照特定规则筛选符合条件的结果。 #### 题目解析 假设该题目涉及从一组数据中找出满足某些条件的数据项,并对其进行输出。以下是一个通用的解决思路: 1. **读取输入数据**:通过标准输入获取必要的参数和数据列表。 2. **定义筛选逻辑**:基于题目描述中的具体要求设计判断函数。 3. **遍历与匹配**:逐一检查每条数据是否符合筛选条件。 4. **输出结果**:如果找到符合条件的数据则立即输出;如果没有,则输出默认提示信息。 下面是具体的代码示例以及解释: ```cpp #include <iostream> #include <vector> using namespace std; int main() { int m, n, s; // 定义变量用于存储转发次数、间隔人数及起始位置 cin >> m >> n >> s; vector<string> participants(m); for(int i = 0; i < m; ++i){ cin >> participants[i]; } bool hasWinner = false; // 标记是否有获奖者 for(int i = s - 1; i < m; i += n){ // 调整索引以便正确映射到参与者数组 if(i >= 0 && i < m){ cout << participants[i] << endl; hasWinner = true; } } if(!hasWinner){ cout << "Keep going..."; } return 0; } ``` 上述程序实现了基本的功能需求,其中包含了几个重要部分: - 使用`vector<string>`来保存所有的参与人员名单[^1]。 - 设置布尔型标志位`hasWinner`用来跟踪是否存在任何合法的赢家。 - 对整个循环过程进行了优化以防止越界访问错误。 #### 注意事项 当实际编写此类竞赛类算法时需要注意边界情况和其他潜在陷阱,比如初始偏移量`s`的有效范围验证等问题都需要额外考虑进去。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值