2020-12-21

2020.12.19 新生赛的重做


前言

部分题目的代码总体上完成了题目要求,但是再O(N)上依然无法通过(尽管以及优化到了9ms但是依然提示Runtime Error),正在寻找方法改进中。


一、A 永远的王 聪明王

在这里插入图片描述这道题目可以看到 科目和数字相对应的
所以首先考虑到结构体数组。
然后简单的使用快排来排序就行了
需要注意的是:关于时间复杂度O(n)的考虑,快速排序的平均复杂度是O(log n),《啊哈算法》中的快速排序,所采用的 基准数,都是直接找数列的最左边的数字。这样的缺陷是 在某些情况下(例如本来就已经排好序的数、各项都相等的数),时间复杂度达到了和冒泡排序的一样的高复杂度—O(N²),所以采用了杨新宇学长那次给的优化过的算法—直接找到中间的变量(结构体)充当基准数,这样来看,时间将得到很大的优化。

但是有一个需要考虑的点是:这是带上结构体的快排。

平时都是简单的对数字单个数据类型排序。现在使用结构体,所以在之前有交换的部分,都需要转换成 结构体 的交换。

考虑到 结构体可以进行整体赋值运算
非常符合交换操作。
当然 在数值比较的时候 仍然要使用结构体内部 的那个int进行大小比较。
通俗的 说就是: int 为主力进行比较,char(科目)被打包到结构体里面跟着跑。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct S{
	char subject[2000];
	long int score;
}subject[1001],p,temp;

void Qsort(int left,int right){ 
	int i,j,t;
	if(left>right){
		return ;
	}
	
	temp=subject[left];
	i=left;
	j=right;
	while(i!=j){
		while(subject[j].score>=temp.score&&i<j){
			j--;
		}
		
		while(subject[i].score<=temp.score&&i<j){
			i++;
		}
		
		if(i<j){
			p=subject[i];
			subject[i]=subject[j];
			subject[j]=p;
		}
	}
	subject[left]=subject[i];
	subject[i]=temp;
	
	Qsort(left,i-1);
	Qsort(i+1,right);
}

int main(){
	long int num=0;
	scanf("%ld",&num);

	struct S t;
	for(long int i=1;i<=num;i++){
		scanf("%s %ld",subject[i].subject,&subject[i].score);
	}

    Qsort(1,num);
    
	
	for(long int i=1;i<=num;i++){
		printf("%s ",subject[i].subject);
	}
	
	return 0;
}

二、I-学妹军训起立蹲下

代码如下(示例):

#include <stdio.h> 
#include <math.h>
int Is(int num){//做一个简单的判断是否为平方数的函数 
      int n=2,rlt=0;
      if(sqrt(num)==(int)sqrt(num)){//这里很重要 判断是否为一个平方数 
      	return 1;
	  }
	  return 0;
	         
} 
int main(){
	int m=0;

	scanf("%d",&m);
	printf("1 ");//无论如何 第一个肯定是站起来的 
	for(int i=2;i<=m;i++){ //因为所有的数都是 1 的整数倍 所以其实就是默认都站起来了
		if(Is(i)){
			printf("%d ",i);
		}
	}
	
	return 0;
} 

这道题其实模拟几次就可以发现规律
因为所有正整数都是 1 的整数倍
其实就是从2开始的人开始计算
简单模拟发现 平方数才是符合规律的
如1 4 9…

所以 — 问题本质就是只需要找平方数

(但是无论用啥方法,sqrt函数也好、自己写也好,依然超时了几百毫秒,O(n)优化还在寻找更好的方法。)

三、L-菜学长的糖糖

在这里插入图片描述

这道题 糖都有各自的编号,糖是有数量的
那么很明显 这题可以用到 桶排序。
编号为1 的糖 则 a[1]++;
最后只需要比较a[i]哪个是奇数即可。

#include <stdio.h> 
#include <math.h>
int Is(int num){//做一个简单的判断是否为平方数的函数 
      int n=2,rlt=0;
      if(sqrt(num)==(int)sqrt(num)){//这里很重要 判断是否为一个平方数 
      	return 1;
	  }
	  return 0;
	         
} 
int main(){
	int m=0;

	scanf("%d",&m);
	printf("1 ");//无论如何 第一个肯定是站起来的 
	for(int i=2;i<=m;i++){ //因为所有的数都是 1 的整数倍 所以其实就是默认都站起来了
		if(Is(i)){
			printf("%d ",i);
		}
	}
	
	return 0;
} 

M-水题

这题画图即可。
拿到题目读题不仔细 导致自己一直以为是两个点到原点的距离差
在这里插入图片描述在数轴上画出来就会有几种分类讨论。
K和N的大小关系分别进行比较。
相等/B再在A 右边的时候,无需移动,直接出0
K>N,A移动到K点即可,出K-A
K<A,B点可能在A点左边找到。
模拟一下即可知道,奇偶性相同的时候不用管,不同的时候,输出1

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

K-小布特烦恼

在这里插入图片描述
这道题仔细看描述就知道,很明显的的一个冒泡排序的题目;
然后加上了“不能超过 一定次数”的限定
所以加了个cnt计数,到达规定的次数直接 No并且return。
如果一直没有触发机制 就yes

此外,此题的输出格式我也进行了一番思考
这类题目 有一种在OJ平台上 是可以 输入一组 立马输出 的
但是我写出来这种方法后,发现似乎不行。
于是进行改进,利用二维数组存储每次的数据
输入完全完成之后,再进行遍历输出

(只可惜依然无法成功A题目…)

#include <stdio.h>
#include <stdlib.h>
//K题:如果想要做到完全输入之后才输出,那就需要考虑二维数组存放。
//可考虑先用一边输入一边输出的方法,这样可以保证先做出来,A的过去。此后有时间可以考虑使用二维数组,锻炼能力 

void Is(int a[],int x);
int main(){
	int n=0;
	scanf("%d",&n);
	
	
	 
	for(int i=0;i<n;i++){//最外围的大循环,用来分别输出每一次的yes no 
		int *a=NULL,x;
		scanf("%d",&x);
		a=(int *)malloc(x*sizeof(int));//开辟动态数组,此时a[x]就可以用了。
		for(int j=0;j<x;j++){
			scanf("%d",&a[j]);//放入数据 
		}
		getchar();//吞字符 
		Is(a,x); 
		free(a);//一定记着要释放内存 否则会出现异常 
	} 
	
	
	
}

void Is(int a[],int x){//可以如此表示数组参数 
	 int  i=0,j=0,cnt=0,t=0;
	 int ex=x*(x-1)/2 -1;
	 for(i=0;i<x-1;i++){
	 	for(j=0;j<x-i;j++){
	 		if(a[j]<a[j+1]){
	 			t=a[j];
	 			a[j+1]=a[j];
	 			a[j+1]=t;
	 			cnt++; 
			 }
			 if(cnt>ex){//每次cnt自己加完了后 就检查一次,一旦过线就直接No退出 
			 	printf("No\n");
			 	return ;
			 } 
		 }
	 }
	 printf("Yes\n");//如果排完序了后 依然没有进入那个底线,那么就说明可以输出Yes 	  
	 return ;//要记得void也需要return 
} 

F-桃花侠大战菊花怪

在这里插入图片描述

这道题其实涉及到博弈论的知识
虽然现在没学习过
但是了解过大致知道了 是通过一系列数学知识,(这个游戏必须理论上双方是50%的胜率),找到一种方法保证最后的胜利。

这题输出结果只有Win/Lose
其实就是让我们模拟、判断出到底一直是Win还是Lose

总结

这次新生赛,最大的收获就是自己对于知识理解和题目解读的不足。
从以下几个方面可以看出。

1、做题经验差

做博弈论题目的时候,哪怕自己没学过博弈论相关知识,但是应该仔细思考,结果只有两种“Win” or “Lose”。哪怕自己一窍不通,也应该知道输出两个内容的一个即可。
此外,模拟思想也不具备,做 蹲下起立和博弈论题目的时候,总是妄想推公式一样的把结论推导出来。但是其实自己多试一试几个样例,就可以找到规律(例如平方数才是需要找的起立的人数),从而使得编程的时候,工作量、思维量减少很多

2.纯裸写代码能力不足

做第一题,快速排序和结构体的知识点,自己其实是以及掌握了的,但是代码永远不是很完善,了解算法原理后,不能做到自己从0开始写出一个完整的算法,总是会缺斤少两。

3、读题能力差

做有关于考察冒泡排序题目的时候,心里看到相关规则的确知道在考察冒泡排序。但是却总是觉得,除了冒泡还在考察其他东西,以至于自己把题目想的很复杂,无从下手。如果真正读懂题意,也就不至于在考场上认为这是一道高难度题目了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值