c++数组题必刷

1.旗鼓相当的对手  P5728

现有 N 名同学参加了期末考试,并且获得了每名同学的信息:语文、数学、英语成绩(均为不超过 150 的自然数)。如果某对学生 <i,j> 的每一科成绩的分差都不大于 5,且总分分差不大于 10,那么这对学生就是“旗鼓相当的对手”。现在想知道这些同学中,有几对“旗鼓相当的对手”?同样一个人可能会和其他好几名同学结对。

输入:第一行一个正整数 N。接下来 N 行,每行三个整数,其中第 i 行表示第 i 名同学的语文、数学、英语成绩。最先读入的同学编号为 1。

输出:一个整数,表示“旗鼓相当的对手”的对数。

思路:开一个二维数组,表示每位同学三科的成绩,再开一个一维数组,表示三科成绩之和,输入数据求出成绩和,用两个for循环把每两位同学的各科成绩都枚举出来,if判断条件,计数器加加,输出。同学可以看着思路去写一遍代码。

#include <iostream>
#include <math.h> 
using namespace std;
int main(){
	int n,a[1010][5],sum[1010];//a数组表示每位同学的三科成绩,sum表示成绩和 
	int cnt=0;//计数器 
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i][1]>>a[i][2]>>a[i][3];
		sum[i]=a[i][1]+a[i][2]+a[i][3];//输入过后立马求和 
	}
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){//把每两位同学都枚举一遍 
			if(abs(a[i][1]-a[j][1])<=5&&
			abs(a[i][2]-a[j][2])<=5&&
			abs(a[i][3]-a[j][3])<=5&&
			abs(sum[i]-sum[j])<=10)//abs表示绝对值,避免出现负数 
			cnt++;//计数器加1 
		}
	}
	cout<<cnt<<endl;//输出 
	return 0;//完美收尾 
}

2.梦中的统计  P1554

Bessie 处于半梦半醒的状态。过了一会儿,她意识到她在数数,不能入睡。Bessie 的大脑反应灵敏,仿佛真实地看到了她数过的一个又一个数。她开始注意每一个数码(0…9):每一个数码在计数的过程中出现过多少次?

给出两个整数 M 和 N,求在序列 [M,M+1,M+2,…,N−1,N] 中每一个数码出现了多少次。

输入:两个用空格分开的整数 M 和 N。

输出:十个用空格分开的整数,分别表示数码 0…9 在序列中出现的次数。

思路:统计时主要是两位数和三位数比较麻烦,得先知道一个整数除以10,就去掉了它的个位,对10取余就得到了它的个位,然后就比较简单了。开一个数组表示每个数字出现的次数,第一个for循环将M到N的数都枚举出来,第二个for循环让这些数有的数字都加1,再枚举数组输出。

#include <iostream>
using namespace std;
int main(){
	int u,v;
	int a[10]={0};//初始化数组 
	cin>>u>>v;
	for(int i=u;i<=v;i++){//枚举出所有数字 
		for(int j=i;j;j/=10){//注意程序执行顺序,先执行下面的,j再改变 
			a[j%10]++;
		}
	}
	for(int i=0;i<=9;i++){//枚举数组输出 
		cout<<a[i]<<" ";
	}
	
	
	return 0;
}

3.珠心算测验  P2141

某学校的珠心算老师采用一种快速考察珠心算加法能力的测验方法。他随机生成一个正整数集合,集合中的数各不相同,然后要求学生回答:其中有多少个数,恰好等于集合中另外两个(不同的)数之和?

输入:

共两行,第一行包含一个整数 n,表示测试题中给出的正整数个数。

第二行有 n 个正整数,每两个正整数之间用一个空格隔开,表示测试题中给出的正整数。

输出:一个整数,表示测验题答案。

思路:开两个大一点的数组,当作两个桶,一个代表各个数的状态,另一个表示每两个数之和的状态,当两个桶的状态同时成立时计数器自增。比如说老师给的数有2和3,那么5也要有,才能成立。

#include <iostream>
using namespace std;
int n,a[101],cnt=0,maxn=0;
int t[200005]={0},g[200005]={0};//初始化为0 
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		t[a[i]]=1;//t表示每个数的状态 
	}
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){//枚举出每两个数 
			g[a[i]+a[j]]=1;//改变每两个数之和的状态 
			maxn=max(maxn,a[j]+a[i]);//这里求出最大值仅仅是为了下面能枚举的少一点,避免超时 
			} 
		}
		for(int i=1;i<maxn;i++){
			if(t[i]&&g[i]){//两个数组都枚举 一遍 
				cnt++;
			} 
		}
	
	cout<<cnt;
	
	return 0;
}

4.插火把  P1789

话说有一天 linyorson 在“我的世界”开了一个 �×�n×n 的方阵,现在他有 �m 个火把和 �k 个萤石,分别放在 (x1​,y1​)∼(xm​,ym​) 和 (o1​,p1​)∼(ok​,pk​) 的位置,没有光并且没放东西的地方会生成怪物。请问在这个方阵中有几个点会生成怪物?

输入:共 m+k+1 行。
第一行为 n,m,k。
第 2 到第 m+1 行分别是火把的位置 xi​,yi​。
第 m+2 到第 m+k+1 行分别是萤石的位置 oi​,pi​。

注:可能没有萤石,但一定有火把。

输出:有几个点会生出怪物。

思路:开一个二维数组,初始化为0,把火把和萤石照亮的地方都变为1,最后遍历数组,输出黑暗地方的个数。

 #include <iostream>
using namespace std;
int n,m,k,x,y,o,p,ans=0;//计数器 
int a[100+5][100+5]={0};//初始化为0 
int main(){
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++){//火把 
		cin>>x>>y;//x代表行,y代表列 
		for(int j=x-1;j<=x+1;j++){
			for(int k=y-1;k<=y+1;k++){
				a[j][k]=1;//注意看图,以火把为中心,3*3的正方形都是亮的 
			}             //都需要点亮 
		}
		a[x-2][y]=1,a[x][y-2]=1,a[x][y+2]=1,a[x+2][y]=1;
	} //再把 最上最下最左最右的位置点亮,火把就完成了 
	
	for(int i=1;i<=k;i++){//萤石 
		cin>>o>>p;//以萤石为中心,5*5的正方形都是亮的 
		for(int j=o-2;j<=o+2;j++){//从萤石的上两行开始,下两行结束 
			for(int k=p-2;k=p+2;p++){//同理 
				a[o][p]=1;
			}
		}
	}
	for(int i=1;i<=n;i++){//遍历整个数组 
		for(int j=1;j<=n;j++){
			if(a[i][j]==0){
				ans++;//计数器加1 
			} 
		}
	}
	cout<<ans;
	
	return 0;
}

5.压缩技术(续集版)P1320

设某汉字由 N×N 的 00 和 11 的点阵图案组成。

我们依照以下规则生成压缩码。连续一组数值:从汉字点阵图案的第一行第一个符号开始计算,按书写顺序从左到右,由上至下。第一个数表示连续有几个 00,第二个数表示接下来连续有几个 11,第三个数再接下来连续有几个 00,第四个数接着连续几个 11,以此类推……

例如: 以下汉字点阵图案:

0001000
0001000
0001111
0001000
0001000
0001000
1111111

对应的压缩码是: 7 3 1 6 1 6 4 3 1 6 1 6 1 3 77 3 1 6 1 6 4 3 1 6 1 6 1 3 7 (第一个数是 N ,其余各位表示交替表示0和1 的个数,压缩码保证 N×N= 交替的各位数之和)

输入:汉字点阵图(点阵符号之间不留空格)。

输出:输出一行,压缩码。

思路:开一个字符串数组,注意这个类型的数组一个位置就是一个字符串,能装一行数字。先把第一行装进去,把n求出来。做一个标记初始化为0,因为图案总是从0开始,然后再用这个标记去判断是去加数量,还是输出个数,当然输出个数的同时也变标记和数量归1。

#include <iostream>
using namespace std;
int main(){
	string a[205];//存储点阵图 ,字符串数组 
	int sum=0;//sum用来记录0/1的个数 
	char c='0';//标记初始化为0 
	cin>>a[0];//输入第一行(数组的一个空间代表一个字符串) 
	for(int i=1;i<a[0].size();i++){
		cin>>a[i];//接下来的都输入 
	}
	cout<<a[0].size()<<" ";//输出n 
	for(int i=0;i<a[0].size();i++){
		for(int j=0;j<a[0].size();j++){
			if(a[i][j]==c) sum++;//判断仍是连续的0/1,sum++ 
			else{ //不是连续的0/1 
				c=a[i][j];//c更换为当前的字符(变标记) 
				cout<<sum<<" ";//输出个数 
				sum=1;//这里一定注意不是0,因为当前那个数也算 
			}
		}
	}
	cout<<sum;//注意这里将最后一个输出 
	
	return 0;
}

 注:这些题目都选自洛谷,并不算难题,希望同学们能学会

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值