【第十二题】排队/搬砖(北理工/北京理工大学/程序设计方法与实践/小学期 )

目录

 题目描述:

乍一看:不就是冒泡

那么转换问题:用逆序数代替最小步数

问题转换:归并排序是什么?怎么在归并排序中计数?

最后吐槽一波。

代码:



 题目描述:

Description

小张在暑假时间来到工地搬砖挣钱。包工头交给他一项艰巨的任务,将一排砖头按照从低到高的顺序排好。可是小张的力量有限,每次只能交换相邻的两块砖头,请问他最少交换几次能够完成任务?

Input

第一行一个整数 n(1 - 300000 ) ,表示砖头数量。

第二行 n 个整数 (-1000000000-1000000000 ) ,表示砖头的高度。

Output

一个整数,表示最少交换几次能够完成任务。

乍一看:不就是冒泡

你要知道,交换,排序,最少步数。

第一个会想到冒泡,但是时间复杂度是n^2,所以一定会超时。

那么转换问题:用逆序数代替最小步数

通过交换相邻数来完成排序所需要的最少交换次数_LUCKYOJ-CSDN博客

 把最小步数转换成求逆序数,但是其实本质还是冒泡排序,看完上面那篇文章你就理解了,或者直接用即可。

关键是,转换成求逆序数,你就可以在csdn上找出一大堆教程,常用的是归并排序求逆序数,至于用树状数组求,是高级玩法了,咱这种上csdn找题解的,就别掺和了,如果有时间,学一学倒是也不错,以后迟早要学树状数组的。

问题转换:归并排序是什么?怎么在归并排序中计数?

十大经典排序算法-归并排序算法详解_小小学编程的博客-CSDN博客_归并排序算法

这篇图画的好,也有实例,便于理解思想,然而不是c语言

归并排序(C语言)详解_爱前端的小菜的博客-CSDN博客_c语言归并排序

这篇是c语言,而且讲的也比较详细,但是他用的递归,递归一方面是速度会拖慢,我之前用斐波那契数列,和这个都是双递归,开到50个左右递归,就已经跑不动了;另一方面递归一层一层地理解起来稍微难一点;还有就是他代码写的稍微有点啰嗦。

实际上有非递归的方式。

逆序数的求法-csdn博客_i-Curve的博客-CSDN博客_逆序数怎么求

最终解答,这篇是c++,不过只用到个>>符号,你就把他当自动规定类型的scanf和printf好了

这篇还讲了树状数组,不过我是没时间研究了,等以后有题非用这算法不可,我才学

不得不提的是,这个人后面还装起来了,/2就除2,还用个>>1位运算装逼,我yue~

最后吐槽一波。

真的不要随便用单个字母当变量名,那个l和1太像了,关键是变量名含义不够清晰,不是一个好习惯。

代码:

#include<stdio.h>
#define SIZE 300010
int pos[SIZE], temp[SIZE];
long long ans = 0;
void sort(int, int, int);
void merge(int, int);
int main(void)
{
//	freopen("input.txt", "r", stdin);
	int n;
	scanf("%d", &n);

	for (int i = 0; i < n; i++)
		scanf("%d", &pos[i]);
	merge(0, n - 1);
	printf("%lld\n", ans);

	return 0;
}
void sort(int left, int mid, int right)
{
	int i = left, j = mid + 1;//i j 并列记录左右分部
	int k = left; //k对应大部
	//左右区都非空,取小记录
	while (i <= mid && j <= right)
		if (pos[i] > pos[j])
		{
			temp[k++] = pos[j++];
			ans += (long long)((mid + 1) - i);//其实没必要,因为width是int范围内
			//这个原理不明hhh
			//大概是把i指向的大数搬到右边要的冒泡步数,也就是我们说的逆序数
		}
		else
			temp[k++] = pos[i++];
	//左右空一边,另一边录入
	while (i <= mid)
		temp[k++] = pos[i++];
	while (j <= right)
		temp[k++] = pos[j++];
	//把temp写入pos,经过排序pos相当于在当前范围归并了一次
	for (i = left; i <= right; i++)
		pos[i] = temp[i];
}
void merge(int left, int right)
{
	if (left < right) //一个以上就递归拆,一个以下,不排序就是排序了
	{
		int mid = (left + right) / 2;
		merge(left, mid);
		merge(mid + 1, right);
		sort(left, mid, right);
		//重点捋一下这个递归调用中sort
		//sort放在递归调用之后,意味着sort其实是倒序执行的
		//也就是说,顺着从大往小拆,然后反过来从小往大归并
		//最后就是,从1个的情况,逐层排序,归并,更新pos
		//最终在初始left和right区间内排序,得到最终的pos
	}
}

C语言课程设计的优点主要体现在以下几个方面: 基础性强:C语言是一门基础性的编程语言,它直接涉及到计算机的内存管理、指针操作等底层知识。学习C语言有助于深入理解计算机的工作原理,为后续学习其他高级语言打下坚实基础。 可移植性好:C语言编写的程序可以在多种操作系统和硬件平台上运行,因此,学习C语言可以帮助学生掌握跨平台编程的技能,提高程序的可移植性。 效率高:C语言具有高效性,它可以直接访问硬件资源,执行效率高。在编写系统级软件、嵌入式系统、游戏开发等领域,C语言具有明显优势。 结构清晰:C语言采用结构化编程思想,有助于培养学生的逻辑思维能力和程序设计能力。通过C语言的学习,学生可以掌握如何合理组织代码、设计算法和数据结构。 资源丰富:C语言拥有丰富的学习资源和社区支持,包括教材、在线课程、论坛等。学生可以通过这些资源自主学习,解决遇到的问,提高编程能力。 实践性强:C语言课程设计通常包含大量的实践环节,如编写小程序、实现算法等。这些实践环节有助于提高学生的动手能力和解决问的能力,使他们更好地将理论知识应用于实际项目中。 综上所述,C语言课程设计具有基础性强、可移植性好、效率高、结构清晰、资源丰富和实践性强等优点。通过C语言的学习,学生可以掌握编程的基本技能,为后续的专业学习和职业发展奠定坚实基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亦梦亦醒乐逍遥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值