c/c++算法 基础题 练手汇总

#练手基础题汇总#

因为是基础题所以都不算难,个人把碰见过的感觉比较好的练手基础题在这里做个汇总,方便查阅。

枚举

  • 一般都是数据量比较小的简单题,难点在于对数据的判断处理。用循环直接对数据区间枚举随后进行判断即可。如果数据量较大,就优化判断条件或者找共性减少运算时间。

1.安全区

题目描述
在一个nn的网格图上有m个探测器,第i个探测器位于(xi,yi)位置,探测半径为ri。
求出n
n个点中有多少个是安全的点,即未被探测的点。

输入
第一行为两个整数n,m(1<=n<=100,1<=m<=n*n)
接下来m行每行3个整数表示xi,yi,ri(1<=xi,yi,ri<=n)

输出
输出一个整数表示答案

样例输入
5 2
3 3 1
4 2 1

样例输出
17

OJ链接

思路: 重点是半径判断,我是用sqrt((x-x1) * (x-x1) + (y-y1) * (y-y1)) > r 来判断是否在检测半径内,同时用二维数组来储存是否能被探测到。

AC代码:

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

bool mymap[101][101];

void func(int x,int y,int r,int n)//中心点 x y 探测半径 r 地图总长 n
{
    
    
	for(int a=x-r;a<=x+r;a++)
	{
    
    
		if(a<1||a>n)//x超界
			continue;
		for(int b=y-r;b<=y+r;b++)
		{
    
    
			if(b<1||b>n)//y超界
				continue;
			if(sqrt((x-a)*(x-a)+(y-b)*(y-b))>r)//不在半径内
				continue;
			//printf("%lf %d\n",sqrt((x-a)*(x-a)+(y-b)*(y-b)),r);
			if(!mymap[a][b])
				mymap[a][b]=true;
		}
	}
}

int main()
{
    
    
	memset(mymap,false,sizeof(mymap));
	int n,m,xi,yi,ri,ans=0;
	cin>>n>>m;
	/*for(int a=1;a<=n;a++)
	{
		for(int b=1;b<=n;b++)
		{
			printf("%d ",mymap[a][b]);
		}
		printf("\n");
	}*/
	for(int temp=0;temp<m;temp++)
	{
    
    
		cin>>xi>>yi>>ri;
		func(xi,yi,ri,n);
	}
	for(int a=1;a<=n;a++)
	{
    
    
		for(int b=1;b<=n;b++)
		{
    
    
			//printf("%d ",mymap[a][b]);
			if(mymap[a][b]==false)
				ans++;
		}
		//printf("\n");
	}
	cout<<ans;
	return 0;
} 

2.统计方形

题目描述
有一个n*m方格的棋盘,求其方格包含多少正方形、长方形(此处长方形不包含正方形)

输入
输入存在多组测试数据。每组测试数据输入两个整数n,m,数字不超过5000

输出
对于每组数据输出一行包含两个整数,分别表示正方形数目和长方形数目

样例输入
2 3

样例输出
8 10

思路: 就是两层循环,代表当前图形的长和宽,长宽一样就是正方形,不一样就是长方形。然后求出这一行能有多少个这种图形(1+(m-b)),再求这一列有多少种这种图形(1+(n-a)),两者相乘就是这个图里有多少种这种图形。然后加到总数里,等循环跑完就是答案。

代码:

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

int main()
{
    
    
	int n,m;
	long long ans1=0,ans2=0;//ans1=正方形 ans2=长方形 
	cin>>n>>m;
	for(int a=1;a<=n;a++)
	{
    
    
		for(int b=1;b<=m;b++)
		{
    
    
			if(a==b)
			{
    
    
				ans1+=(1+(n-a))*(1+(m-a));	
			} 
			else
			{
    
    
				ans2+=(1+(n-a))*(1+(m-b));
			}
		}
	}
	cout<<ans1<<" "<<ans2;
	return 0;
}
  • 但是这样复杂度会比较高,可能会超时,所以有第二种求法。先求出总的矩形个数,再用一层循环求出正方形个数,总的减去正方形的就是长方形的。

AC代码:

#include <bits/stdc++.h>
using namespace std;
 
int main ()
{
    
    
    /*对于一个n*m的棋盘,共有矩形 (m+m-1+m-2+...+1)*(n+n-1+n-2+...+1)
    即[m*(m+1)/2]*[n*(n+1)/2]个,这一步可知用前一个式子循环道加,也可版用后一个式子直接算;
    共有正方形(假设m>n) m*n+(m-1)*(n-1)+...+(m-n+1)*1 个,这步用循环做就行;
    长方形就用 矩形权数 减去 正方形数 就行了。*/
    int n,m;
	while(scanf("%d %d",&n,&m)!=EOF)
	{
    
    
		long long sum1=0;
	    for(int i=1;i<=min(n,m);i++)
	    {
    
    
	        sum1+=(n-i+1)*(m-i+1);
	    }
	    printf("%lld ",sum1);
	    long long sum2=1LL*n*(n+1)/2*1LL*m*(m+1)/2;//1
	    printf("%lld\n",sum2-sum1);
	} 
    return 0;
}

3.连续自然数和(尺取法)

题目
对于给定自然数N,求出存在多少个连续自然数段,长度至少为2,使得这些连续的自然数段之和为N。

输入
输入有若干行,每行一个正整数n。(1<=n<=2000000)

输出
对于每组测试数据输出第一个数字表示答案

样例输入
9
10000

样例输出
2
4

思路: 可以用for循环暴力循环出来,但是我下面是用的尺取法,来减少复杂度。

AC代码:

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

int main()
{
    
    
	int n;
	while(scanf("%d",&n)!=EOF)
	{
    
    
		int ans=0,temp=0,f=1,e=1;//答案个数 中间值 头 尾
		while(n!=0)//尺取
		{
    
    
			while(temp<n&&e<n)
			{
    
    
				temp+=e;
				e++; 
			}
			if(temp<n)
			{
    
    
				break;
			}
			if(temp==n&&e-f>=1)
			{
    
    
				ans++;
			}
			temp-=f;
			f++;
		}
		printf("%d\n",ans);
	}
	return 0;
} 

4.蓝桥杯 数字分组

问题描述
  输入任意10个浮点数,根据它们的聚集程度划分为3组,输出每一组的平均值。
  提供老师上课讲的一种思路:将10个数字进行在数轴上排序,然后计算每两个点间的距离,在所有的距离中选取两个最大距离处断开,这样就把10个数字分为了3组。
  本题难度较大,如果深入讨论会比较复杂,大家可以只考虑如下面样例所示的分组情况非常简单的情况,只要简单情况能够成功计算,本题就能得分。
  另外,本题内容有些超前,推荐大家自学一下数组那一章中第一节一维数组,然后使用一维数组来做。排序算法可以参考trustie平台上传的冒泡排序法参考资料。

输入格式
  十个待输入的浮点数,使用空格隔开

输出格式
  三组数的平均数,每输出一个需要换行

样例输入
一个满足题目要求的输入范例。
例1:
50.4 51.3 52.3 9.5 10.4 11.6 19.1 20.8 21.9 49.6
例2:
8.6 7.4 3.5 17.9 19.1 18.5 37.6 40.4 38.5 40.0

样例输出
与上面的样例输入对应的输出。
例1:
10.5
20.6
50.9
例2:
6.5
18.5
39.125

思路: 直接循环枚举检测间隔即可。

AC代码: OJ链接

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

double shuzu[10];
int main()
{
    
    
	double max1=0,max2=0,m1,m2;
	for(int a=0;a<10;a++)
	{
    
    
		scanf("%lf",&shuzu[a]);
	}
	sort(shuzu,shuzu+10);
	for(int a=0;a<9;a++)
	{
    
    
		double temp=shuzu[a+1]-shuzu[a];
		if(temp>max1)
		{
    
    
			max2=max1;
			m2=m1;
			max1=temp;
			m1=a;
		}
		else if(temp>max2)
		{
    
    
			max2=temp;
			m2=a;
		}
	}
	double temp=0;
	for(int a=0;a<=min(m1,m2);a++)
	{
    
    
		temp+=shuzu[a];
	}
	printf("%g\n",temp/(min(m1,m2)+1));
	temp=0;
	for(int a=min(m1,m2)+1;a<=max(m1,m2);a++)
	{
    
    
		temp+=shuzu[a];
	}
	printf("%g\n",temp/(max(m1,m2)-min(m1,m2)));
	temp=0;
	for(int a=max(m1,m2)+1;a<=9;a++)
	{
    
    
		temp+=shuzu[a];
	}
	printf("%g\n",temp/(9-max(m1,m2)));
	return 0;	
} 

猜你喜欢

转载自blog.csdn.net/qq_45698148/article/details/108367693