Codeforces大战苏维埃 12月17,18签到题解析

众所周知,国内有不少刷题宝地 力扣  牛客  洛谷    PTA    头歌 等等。

但是要说到世界有名的,那必须是我们最受欢迎的算法网站 Codeforces,该网站的评判机制,题目质量都是很棒的,受到各大算友的喜爱,但是对于我们水平稍低的,暂时可能就是去做做签到题练练手,也是在一步一步成长的过程中,看到自己的积分(codeforces有一个积分机制)慢慢上去,会有自豪感,所以我们来解析一波近些日的签到题。

对于我们是开的新坑,所以我们说明一下以后题目解析的顺序:

1:翻译解释题目(因为codeforces上都是英文,写题目的时候可以网页翻译,但是机器翻译不一定准确,语序也会影响,所以要加入点个人的理解)

2:思路讲解

3:遇到的问题以及解决方法

4:代码展现

Dec/18/2022

Codeforces大战苏维埃 12月17,18签到题解析_第1张图片

Codeforces大战苏维埃 12月17,18签到题解析_第2张图片

 题目解释:题目即要求输入一个2x2的各个数字不同的数字矩阵,然后这个数字矩阵可以顺时针旋转90°。然后题目给出了一个定义:如果本体或者旋转之后的矩阵中存在满足以下两个条件的

在每一行中,第一个元素小于第二个元素;

在每一列中,第一个元素小于第二个元素。

我们则称之为漂亮的矩阵。

然后我们的输入要求,先输入一个 t  表示案例总数(也就是我们这个题目里面最开始的输入 6  在codefores里面 几乎所有的题目第一个要求输入的都是案例数)

接下来输入t组2x2的数字 用于组成矩阵。

输出即 若此组矩阵是漂亮的矩阵 ,则输出YES  反之则为NO;

题目分析结束,那么开始我们的思路分析。

思路一:简单粗暴法。因为我们的矩阵是顺时针旋转90°,在不断的旋转中,其实算上自身,一共也才四个不同的矩阵,而且我们在已知本体矩阵的前提下,是可以把这四个都写出来的,那么我们就可以直接创建四个二维数组,然后对这个四个二维数组进行判断。

思路二:进行多次旋转,其实每个位置都可能会出现四个数中的任何一个数,其实就相当于我们把四个数随机放到四个格子中,那么我们可以不创建四个二维数组,我们把四个数存储,只需要创建一个二维数组,把四个数随机分配到里面即可。

遇到的问题以及解决方案:

第一个:数据的存储,我们采用二维数组来表示这个矩阵。

第二个:对于思路二中的随机分配,用一个简单粗暴的方法就是嵌套四个for循环

在这里我们给出思路一的代码(我才不会承认我比较懒不想写)

#include  
int main() 
{ 
 int a[2][2];
 int b[2][2];
 int c[2][2];
 int d[2][2];
 int i=0,g=0,h=0,n;
 scanf("%d",&n);
 for(i=0;i

这次比赛的A题也是个签到题,简直太容易了,就是让你写个加法没啥好说的,我们就直接跳过。

Dec/17/2022

Codeforces大战苏维埃 12月17,18签到题解析_第3张图片

 题目解释:给出一个长度为n的序列 每一个元素代表一个塔,塔上有东西,元素的下标代表塔的序号,记作a1,a2,a3......an , 元素的数字代表塔上物品的多少,在1~n的范围内有ai和aj 如果ai>aj,那么可以从ai上拿一个给aj,这操作会使得ai少一个,aj多一个。那么在一系列操作之后,a1上最多有多少个东西?

我们再拿给是示例解释以下题目,例如第一组1 2 3  ,因为2>1,所以移动之后我们就是2,1,3然后因为3>2,所以我们在进行一次操作得到3,1,2此时的第一个塔等于3,已经是最大了,所以输出3,当然我们如果这么来看,一开始1,2,3,我们因为3>1,直接让他们进行操作变成2,2,2,之后便不能操作了,此时的2并非最大值。

那么问题来了,我们该如何确定怎么操作能最大呢?

既然要a1最大,那么a1要尽可能的多从别人那里获得,尽可能的多。

我们从刚刚第一组示例1,2,3来看看,我们想出了两个操作方法,为何第二个方法不行呢?我们来看看两者之间最后的值差1,不难看出,我们第二种方法让1,3直接操作,就导致了1操作完之后变成了2 直接丧失了与2的“求偶”机会,这就导致缺失了方法一中的1,2操作而增加的1,所以,我们是不是可以有这么一个想法:尽可能的增加操作次数,我们从小到大进行操作就可保证a1最后的值最大?

那么有了这个思路,我们就可以去试试,那题目所给的最后一组示例3,8,6,7,4,1,2,4,10,1

那么我们就是依次和4,6,7,8,10进行操作(当然,操作过程中可能会导致超过后面的某个数,直接跳过就行,我们只需要保证每次操作都是与可操作数里面最小的进行)最后结果的确是9,那么说明我们的想法有一定的可行性。有了想法,我们就可以动手操作。

遇到的问题及其解决方法:

一:我们既然要和最小的进行操作,那么怎么找到可操作数里面最小的?

解决方法:如果时间允许的话,每次操作前,你都可以遍历一次找最小的,这个想法也不是不可以。我的话,我最先想到的是先从小到大排序,之后就都不需要再去找最小的了。

二:操作之后的数量变化。这个是个不难的数学问题,相信应该都会。

所以最后我们的代码如下:

#include  
#include
#include
int comp(const void*p,const void*q)
{
	return *(int*)p-*(int*)q;
}
int main() 
{ 
 long long int g,m,a[200001]={0},b,i,t,n; 
 scanf("%lld",&m);
 for(g=0;gb){
     		b=ceil((a[i]+b)/2.0);
     		if(b>a[n-1]) break;
		 }
	 }
	 printf("%lld\n",b);
 }
 return 0;  
}

特别注意:数组大小一定要大胆点给,我就是太小了,导致时间超限,掉大分,血的教训!!

今天的解析先到这里,如果有不对的,或者有更好思路的,欢迎大家在评论区讨论

你可能感兴趣的:(c新手入门题练习,算法,c语言,c++)