C/C++算法编程竞赛实战篇:南邮大学生程序设计竞赛“鼎新杯”

目录

前言

已经很久一段时间没有更新了,这期间一直忙着处理校内的考试、作业和比赛,非常抱歉。今天的这篇博客想给大家带来的是我校大学生程序设计竞赛中我完成的部分题目以及我的想法。里面的部分题目还是有难度的,值得我们细细推敲。本文仅用做学习用途,相关解释权归于南京邮电大学承办方。同时本人是小白,有错误欢迎指正,不喜勿喷!那么事不宜迟,我们马上开始。

一、S001 阮小妍要当程序媛,妈妈可开心啦

1.题干展示

2.思路分析

3.代码示例

二、S002 要看一辈子的Mygo哦~

1.题干展示

2.思路分析

3.代码示例

三、S003 看管人太多导致的

1.题干展示

2.思路分析

3.代码示例

四、S005 可再生清洁能源

1.题干展示

2.思路分析

3.代码示例

四、S006 纸片人

1.题干展示

2.思路分析

3.代码示例

总结

那么这就是我第一次竞赛试水之后的总结啦!如果这篇文章对你有所帮助还请多多支持!!



前言

已经很久一段时间没有更新了,这期间一直忙着处理校内的考试、作业和比赛,非常抱歉。今天的这篇博客想给大家带来的是我校大学生程序设计竞赛中我完成的部分题目以及我的想法。里面的部分题目还是有难度的,值得我们细细推敲。本文仅用做学习用途,相关解释权归于南京邮电大学承办方。同时本人是小白,有错误欢迎指正,不喜勿喷!那么事不宜迟,我们马上开始。

一、S001 阮小妍要当程序媛,妈妈可开心啦

1.题干展示

2.思路分析

这是最基础的送分题了。如果这题还有犹豫的话说明平时根本没学。我们按要求随便输出一个字符串即可。

3.代码示例

#include <bits/stdc++.h>
using namespace std; 

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cout << "hello sast" << "\n";
    return 0;
}

二、S002 要看一辈子的Mygo哦~

1.题干展示

2.思路分析

本题考查简单的选择结构,只需按照题目的意思列出分支并进行相应操作即可。

3.代码示例

 

#include <bits/stdc++.h>
using namespace std; 

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t, h; cin >> t;
    if (t >= 0 && t <= 10)
    {
        h = 3 * t + 10;
    }
    else if (t > 10 && t <= 25)
    {
        h = 3 * t + 10;
    }
    else if (t > 25)
    {
        h = 565;
    }
    cout << h << "\n";
    return 0;
}

三、S003 看管人太多导致的

1.题干展示

2.思路分析

这一题的大致工作逻辑如下:首先遍历范围内的每一个数,并且取出这个数的每一位(我用的动态数组进行存储),然后判定在这些数中是否存在相邻位是相邻的数,如果有就进行输出。这题第一需要注意的是如果我们如果不使用动态数组很容易在遍历时忽略数组此时下标的部分性导致后面没有用到的部分也参与了遍历(即下标过头了)。第二个我们需要注意的是两位数的情况需要单独讨论,具体原因是下标只有0和1两个,会产生循环遍历条件的错误。

3.代码示例

#include<bits/stdc++.h>
using namespace std;

int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int a,b;cin>>a>>b;
	int count=0;//用于确定开辟多少空间存储每一位的数字	
	int index=0;//用于指示下标
	for(int i=a;i<=b;++i)
	{
		int j=i;
		//先遍历位数试试水
		while(j)
		{
			j/=10;
			count++;
		}
		//准备相应的动态数组去接收数据
		int* c=new int[count];
		j=i;
		while(j)
		{
			int temp=j%10;
			c[index]=temp;
			j/=10;
			index++;
		}
		//这边必须分情况讨论
		if(index==2)
		{
			if(c[0]+1==c[1]||c[0]-1==c[1])
			{
				cout<<i<<"\n";
			}
		}
		else
		{
			for(int k=0;k<count;++k)
			{
				if(c[k]+1==c[k+1]||c[k]-1<=c[k+1])
				{
					cout<<i<<"\n";
					break;
				}
			}
		}
		//重制count和index
		count=0;index=0;
		delete[]c;
	}
	return 0;
}

四、S005 可再生清洁能源

1.题干展示

2.思路分析

这一题可以用枚举法求解。接下来是常规的分析思路。我们要搞清楚的是究竟哪些风车需要被拆掉。那么由题意可知,我们可以有不同的拆法,由此可以得到拆完后最近风车的距离组,再求这个最近距离组中的最大值。那我们拆除哪一座呢?我们继续分析。

对于题干中给的示例,我们有:

显然此时1、2的距离最小,为1;距离第二小的是5和7,7和9。无论将1和2中的那个去除都不会影响接下来距离最小值的最大值的取法(取5和7或者7和9之间的距离,距离为2)。而拆除其他风车都会使得距离最小值为1而不是2。但是下一种情况就不是如此了。

对于这一种情况,我们有:

这时我们只能拆除4,因为如果拆3或者5就会导致距离最小值是1而不是距离最小值组的最大值2。

除此之外还有一种特殊情况:最小距离风车组不止一组而且并不相邻。此时无论去除最小风车组成员中的哪一个风车,最终距离的最小值都不会发生改变。

由此我们可以窥探到一些规律,并有了初步的想法:我们将风车的位置坐标传入数组并进行排序,然后我们再看初始状态下距离的最小值是在哪两个风车间取到的。如果两个风车位于中间部分,那么去除哪一个都是一样的;如果两个风车位于风车列的两端,那么我们最好去除更靠近中心的那个风车。总而言之就是必须拆散初始距离最小的风车对。

当然,我们有更为鸡贼的办法。显然,去除一个风车之后的风车距离最小值一定大于等于初始的风车距离最小值。既然如此,我们得出风车之间的距离并且存入数组。进行排序之后一般情况下数组第二位的数据即为所求值。有多个同时取到最小值的风车对时,如果不存在相邻的风车对,那么风车距离最小值不变。那么我们就可以得出最终的代码了。

3.代码示例

#include<bits/stdc++.h>
using namespace std;

int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int temp;
	int n;cin>>n;
	int*a=new int[n];
	int*b=new int[n-1];
	for(int i=0;i<n;++i)
	{
		cin>>temp;
		a[i]=temp;
	}
	sort(a,a+n);
	for(int i=0;i<n-1;++i)
	{
		b[i]=a[i+1]-a[i];
	}
    sort(b,b+n-1);
	if(b[1]==b[0])
	{
		cout<<2*b[1]<<"\n";
	}
	else
	{
		cout<<b[1]<<"\n";
	}
	delete[]a;
	delete[]b;
	return 0;
}

四、S006 纸片人

1.题干展示

2.思路分析

很多同学反映这道题看不懂,但实际上这一题本质上只是一个计算面积的问题。最最坑人的一点是,幕墙放置位置在数组里的下标是n/2而不是(n/2)+1!!!笔者就是因为这一点而与金奖失之交臂。显然,对于幕墙来说,只有部分遮挡和完全遮挡两种情况。在本题中,若地面低于幕墙基础高度,我们就补上对应的面积(幕墙延伸到地下)。

3.代码示例

#include<bits/stdc++.h>
using namespace std;

int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int h,n;cin>>h>>n;//光幕的高度与宽度
	int* hx=new int[n];//动态数组存储横向各点高度
	int* hy=new int[n];//动态数组存储纵向各点高度
	int pos=(int)(n/2);
	for(int i=0;i<n;++i)cin>>hx[i];
	for(int i=0;i<n;++i)cin>>hy[i];
	//记录横向和纵向的基础高度
	int basisx=hx[pos];
	int uplinex=basisx+h;
	int basisy=hy[pos];
	int upliney=basisy+h;
	int sx,sy;//面积
	sx=h*n;
	sy=sx;//面积的初始值
	for(int i=0;i<n;++i)
	{
		if(hx[i]>=basisx&&hx[i]<uplinex)
		{
			sx-=hx[i]-basisx;//部分遮挡
		}
		if(hx[i]>=uplinex)
		{
			sx-=h;//全遮挡
		}
		if(hx[i]<basisx)//延伸到地下
		{
			sx+=basisx-hx[i];
		}
	}
	for(int i=0;i<n;++i)
	{
		if(hy[i]>=basisy&&hy[i]<upliney)
		{
			sy-=hy[i]-basisy;//部分遮挡
		}
		if(hy[i]>=upliney)
		{
			sy-=h;//全遮挡
		}
		if(hy[i]<basisy)//延伸到地下
		{
			sy+=basisy-hy[i];
		}
	}
	if(sx>sy)
	{
		cout<<0<<"\n";
		cout<<sx<<"\n";
	}
	else if(sx<sy)
	{
		cout<<1<<"\n";
		cout<<sy<<"\n";	
	}
	delete[]hx;
	delete[]hy;
	return 0;
}

总结

那么这就是我第一次竞赛试水之后的总结啦!如果这篇文章对你有所帮助还请多多支持!!
  • 24
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值