C++ 数组一本通平台讲解
接上次数组讲解...2034 - 2050,1102 - 1149,1839接下来是代码以及讲解
2034:【例5.1】反序输出
#include<iostream>
using namespace std;
int x[110];
int **in()
{
int i=1;
while(cin>>x[i++]);//输入x,如果输入了就将其读入i+1中,否则退出循环
for(i=i-2;i>0;i--) cout<<x<<' ';//逆序输出,注意下标必须从i-2开始
return 0;
}
这道题的解题思路就是将所有变量存入数组当中,在从尾到头输出
2035:【例5.2】平移数据
#include<iostream>
using namespace std;
int x[1000001];
int **in()
{
int i,n;
cin>>n;
for(i=1;i<=n;i++) cin>>x;
for(i=2;i<=n;i++) cout<<x<<' ';
cout<<x[1]<<endl;
return 0;
}
这道题是将第一个位置上的数放在较后输出,所以我们先输出前面的数,较后输出第一位即可
2036:【例5.3】开关门
#include<iostream>
using namespace std;
bool y[1100];//bool类型的一维数组,bool类型的数组初始值为0,也就是false
int **in()
{
int i,j,x;
cin>>x;
for(i=1;i<=x;i++) for(j=1;j<=x;j++) if(j%i==0) y[j]=!y[j];
//i模拟的是服务员,j模拟的是门,当j号门符合j号服务员的"相反操作"时取反
//y[j]=!y[j]的意思就是将!y[j]的bool值赋给自己
//!是"非",作用是将其后方的bool变量的true变为false,false变为true
//较后再赋值给自己,就完成了取反操作了
for(i=1;i<=x;i++) if(y) cout<<i<<" ";
return 0;
}
理解题意,通过对一维数组的思考就能够做出来了
2037:【例5.4】约瑟夫问题
#include<iostream>
bool a[1100];
int **in()
{
int i,n,m,f=0,t=0,s=0;
cin>>n>>m;
while(f<n)//如果出圈的人数小于总人数时执行这个循环
{
t++;//人的编号,每一次增加1
if(t==n+1) t=1;//如果t增加超过了n个人,那么就返回到编号为1的人
if(a[t]==false) s++;//如果这个人没有出圈,就把这个人数进去
if(s==m)//如果数到了第m个人
{
s=0;//计数器归零,方便下次使用
cout<<t<<' ';//输出这个人的编号
a[t]=true;//将这个人几率为出圈者
f++;//将出圈人数增加
}
}
return 0;
}
这一道题目比较复杂,因为这个数组并非一条线,而是一个圈,头和尾是相连的,需要特殊的处理。( 不会的要多加思考,想明白为什么要这么做 )
2038:【例5.5】较大数位置
#include<iostream>
using namespace std;
int **in()
{
int i,x,n,**xn=-1,**xn_i;//较大值设置为-1,方便后续的比较
cin>>n;
for(i=1;i<=n;i++)
{
cin>>x;
if(x>**xn)//如果输入的数要比较大数大
{
**xn=x;//替换较大数
**xn_i=i;//记录较大数的位置
}
}
cout<<**xn_i<<endl;//输出较大数的位置
return 0;
}
这道题是找到较大值,找较大值得方法使用打擂台的方式,在讲 If 的时候讲过了,但是当时并没有学习数组,与数组的处理方式也有所不同,但是本质上还是类似的。
2039:【例5.6】冒泡排序
冒泡排序,这是一种排序的算法,现在我们已经学习了数组了,可以开始了解一些算法了。
那么,什么是冒泡排序
这是一段数字,我需要它们从小到大进行排列
4 1 3 2
要怎么排呢,首先,我们先取出第一个数 ( 4 ),发现后面的数 ( 1 ) 要小于它,于是,我们交换它们的位置,得到了
1 4 3 2
继续往后找,取出第二个数 ( 4 ),发现后面的数 ( 3 ) 也不该出现在第二个数 ( 4 ) 的后面,于是我们再交换它们俩,得到了
1 3 4 2
通过再一次交换,我们就将较大的数 ( 4 ),放在了最末尾的位置上
1 3 2 4
下一轮交换,我们发现第二个数 ( 3 ) 和第三个数 ( 2 ) 没有按照顺序,就交换它们
然后,这个数组就变的有序了
1 2 3 4
#include<iostream>
using namespace std;
int a[10000000];
int **in()
{
int i,j,n;
cin>>n;
for(i=1;i<=n;i++) cin>>a;
for(i=1;i<n;i++) for(j=1;j<n;j++) if(a[j+1]>a[j]) swap(a[j+1],a[j]);
//排序n-1次,每次从1开始到n-1,反复判断下一个变量是否大于自身,是则交换
for(i=1;i<=n;i++) cout<<a<<endl;
return 0;
}
其中,第九行是冒泡排序的核心,这个是学习冒泡排序需要理解的
2040:【例5.7】筛选法找质数
题目都给出了 " 筛选法 ",那就是直接枚举加判断即可
下面 13 至 20 行是判断素数的核心代码,理解程序如何判断素数
#include<iostream>
#include<cstdio>
#include<c**th>
using namespace std;
int **in()
{
int i,j,n;
bool flag=true;
cin>>n;
for(i=2;i<=n;i++)
{
flag=true;//默认此数为素数
for(j=2;j<=sqrt(i);j++)//素数判断方法
{//从2到sqrt(i) 即i的算术平方根
if(i%j==0)//判断是否整除
{
flag=false;//如果整除,就不是素数了
break;//退出本层循环
}
}
if(flag) cout<<i<<endl;//如果是素数就输出此素数
}
return 0;
}
对于大于 sqrt ( i ) 的数无需进行判断,这是一种优化
2041:【例5.9】新矩阵
这道题是处理二维数组的题目,要求将两条对角线上的点加上 10
那么,我们怎么判断对角线呢
我们来看看对角线上的点有什么特点
( 1 , 1 ) ( 2 , 1 ) ( 3 , 1 ) ( 4 , 1 )
( 1 , 2 ) ( 2 , 2 ) ( 3 , 2 ) ( 4 , 2 )
( 1 , 3 ) ( 2 , 3 ) ( 3 , 3 ) ( 4 , 3 )
( 1 , 4 ) ( 2 , 4 ) ( 3 , 4 ) ( 4 , 4 )
我们先来看由左上角到右下角的对角线,我们发现他们的 X 坐标和 Y 坐标相同。
再来看由右上角到左下角的对角线,我们发现他们的 X 坐标和 Y 坐标的和为边长加 1。
这下就好办了,我们枚举每一个点,然后用上述方法判断它是否为对角线上的点,如果是,就增加 10,否则就枚举下一个点
#include<iostream>
using namespace std;
int a[21][21];
int **in()
{
int n,i,j;
cin>>n;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
cin>>a[j];
if(i==j||i+j==n+1) a[j]+=10;//判断是否为对角线上的点
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++) cout<<a[j]<<' ';//输出
cout<<endl;
}
return 0;
}
这道题难点是判断对角线上的点,其他就没有什么难的了
2042:【例5.10】稀疏矩阵
这道题目就是以另外一种方式存储矩阵,应为这个矩阵比较稀疏,利用其稀疏的特点,存储每一个不为 0 的点的坐标和值,这样就可以做到存储的效果了
#include<iostream>
using namespace std;
int **in()
{
int i,j,n,m,x;
cin>>n>>m;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
cin>>x;
if(x!=0) cout<<i<<' '<<j<<' '<<x<<endl;
//如果此点的值不为0,那么就将它的位置和值得信息输出即可
}
}
return 0;
}
还是非常简单的
2043:【例5.11】杨辉三角形
这道题很简单,我们不是模拟一个三角形 ( 毕竟没有三角形数组嘛... ),利用二维数组模拟一个三角形,并去计算这个三角形,让它达到结果即可
#include<iostream>
using namespace std;
int a[40][40];
int **in()
{
int i,j,n;
cin>>n;
for(i=0;i<n;i++)
{
a[0]=1;
a=1;//将三角形的两条边换成1
}
for(i=0;i<n;i++) for(j=1;j<i;j++) a[j]=a[i-1][j-1]+a[i-1][j];
//核心计算,如何计算到此点的值,我们按照杨辉三角形的公式可知
//一个点的值=它上方的点的值+它上方的点的左边的值
for(i=0;i<n;i++)
{
for(j=0;j<=i;j++) cout<<a[j]<<' ';
cout<<endl;//输出
}
return 0;
}
重点在公式处,理解了公式,这道题也就不难了
2044:【例5.12】回文字串
回文字符串的概念是 : 从前往后读或从后往前读都是一样的,那么就是说字符串折中后两边都互相颠倒
#include<iostream>
#include<cstring>//新的头文件下面的strlen需要用到它
using namespace std;
char s[105];
int **in()
{
cin>>s;
int i,l=strlen(s)-1;
for(i=0;i<l/2;++i)//特别注意下标是从0开始的
{
if(s!=s[l-i-1])//判断是否是回文的
{
cout<<"No";
return 0;
}
}
cout<<"Yes";
return 0;
}
重点是判断的方法
2045:【例5.13】蛇形填数
这道题较难理解,目前要做出这道题虽然不是不可以,但是是很复杂的,下面有比较好理解的方式
#include<iostream>
#include<c**th>
using namespace std;
int **p[30][30];
int **in()
{
int i,j,n,sum,ans=0,x,y,facing=1;
//sum是需要填充的格子总数,ans是已填充的格子总数,x,y是点的位置,facing是面向的方向
cin>>n;
sum=n*n;//总共需要填充n*n个格子
x=1;y=n;//出始位置为(1,n)
while(ans<sum-1)//填充了超过sum-2个格子时退出
{
if(facing==1)//如果下一个方向是下
{
if(x<n&&**p[x+1][y]==0)//判断是否可以进行
{
**p[x][y]=ans+1;//填充格子
x++;//点的位置的修改
ans++;//已填充的格子数增加
}
else facing++;//方向改变
}
if(facing==2)//如果下一个方向是左
{
if(y>1&&**p[x][y-1]==0)
{
**p[x][y]=ans+1;
y--;
ans++;
}
else facing++;//同上
}
if(facing==3)//如果下一个方向是上
{
if(x>1&&**p[x-1][y]==0)
{
**p[x][y]=ans+1;
x--;
ans++;
}
else facing++;//同上
}
if(facing==4)//如果下一个方向是右
{
if(y<n&&**p[x][y+1]==0)
{
**p[x][y]=ans+1;
y++;
ans++;//同上
}
else facing=1;//变为下
}
}
if(n&1) **p[(n+1)/2][(n+1)/2]=n*n;//硬核处理较后一个点...
else **p[n/2][n/2]=n*n;//硬核处理较后一个点...
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++) cout<<**p[j]<<' ';
cout<<endl;//输出
}
return 0;
}
这个代码好理解的原因是它是循序渐进的,通过对点的变化而赋值,其实这就是广搜 ( BFS )
2046:【例5.15】替换字母
#include<iostream>
#include<cstring>
#include<string>//string类型,这是今后字符串类型的重头戏,个人认为比char数组更好用
using namespace std;
string a;
char x,y;
int **in()
{
getline(cin,a);//读入字符串类型a
cin>>x>>y;
int i,l=a.size();//a.size()是求a的字符串长度
for(i=0;i<l;i++) if(a==x) a=y;//遍历字符串a,找到合适的字符并替换
cout<<a<<endl;//输出a
return 0;
}
string 类型字符串是我个人认为十分好用且主要使用的字符串类型,使用方便,也有很多的功能
2047:【例5.16】过滤空格
判断空格数不输出即可
#include<iostream>
#include<string>
using namespace std;
string a;
int **in()
{
getline(cin,a);//输入
int i,l=a.size();//算长度
cout<<a[0];//输出第一位,方便后续判断不越界
for(i=1;i<l;i++) if((a==' '&&a[i-1]!=' ')||a!=' ') cout<<a;
//如果此位是空格并且上一位不是空格或本身就不是空格就可以输出
return 0;
}
2048:【例5.18】串排序
这道题使用 string 类型会比 char 类型更加简单
#include<iostream>
#include<string>
using namespace std;
string x[30];
int **in()
{
int i,j,n;
cin>>n;
getchar();
//因为在前面使用cin输入后留下了回车,所以我们要先将这个回车给消灭掉
for(i=1;i<=n;i++) getline(cin,x);
//使用getline(cin,x)读入x的值
for(i=1;i<=n;i++) for(j=1;j<n;j++) if(x[j]>x[j+1]) swap(x[j],x[j+1]);
//冒泡排序,其中字符串的比较规律比较特殊
for(i=1;i<=n;i++) cout<<x<<endl;
//按照顺序输出
return 0;
}
字符串的比较顺序 : 首先,我们找到四个字符串
字符串 A : TouBiShouCang
字符串 B : DianZanGuanzhu
字符串 C : DONOTBaiPiao
字符串 D : DONOTBaiPiao
我们来进行比较操作,首先比较 A 和 B,我们看到第一位,T 和 D,从 ASCII 表我们可以看出,D ( 68 ) < T ( 84 ),所以我们判断 B < A
如果开头有着相同字符要怎么比较 ? 再来,我们比较 B 和 C,看到第一位,发现两个字符相同,那么我们就继续找下一位,发现 O ( 79 ) < i ( 105 ),所以,我们就判断 C < B
如果两个字符串相同,那么它们就是相等的,例如字符串 C 和 D
2049:【例5.19】字符串判等
这道题需要清除空格以及改变大小写,很简单,这里我使用 string 类型来写
#include<iostream>
#include<string>
using namespace std;
string a,b,c,d;
int **in()
{
getline(cin,a);
getline(cin,b);
int i,j,l=a.size(),r=b.size();
for(i=0;i<l;i++)
{
if(a!=' ')//过滤空格
{
if(a>='a'&&a<='z') c.push_back(a-32);
//push_back()就是将括号内的数放入字符串的较后面
else c.push_back(a);
}
}
for(i=0;i<r;i++)
{
if(b!=' ')
{
if(b>='a'&&b<='z') d.push_back(b-32);
//将b-32,也就是将其大写字母放入末尾
else d.push_back(b);
}
}
if(c==d) cout<<"YES"<<endl;//判断是否相等
else cout<<"NO"<<endl;
return 0;
}
题目在处理完空格及大小写后就会非常容易了
2050:【例5.20】字串包含
#include<iostream>
#include<string>
using namespace std;
string a,b;
int **in()
{
cin>>a>>b;
if(a.size()<b.size()) swap(a,b);//保证在大的字符串中找小的字符串
a+=a;
//a+=a -> a=a+a
//例如 a="TouBi"
//a+=a a="TouBiTouBi"(双倍快乐)
//作用是让下面的find函数可以进行循环查找
if(a.find(b)!=a.npos) cout<<"true"<<endl;
//find()是在字符串中查找括号内字符串的函数
//如果存在则返回其开始的位置,不存在则返回npos(即结束点)
//这个函数可以方便查找字符串中是否存在某个字符串
else cout<<"false"<<endl;
return 0;
}
巧妙利用内置函数偷懒。
1102:与指定数字相同的数的个数
#include<iostream>
using namespace std;
int a[101];
int **in()
{
int i,n,sum=0,m;
cin>>n;
for(i=1;i<=n;i++) cin>>a;
cin>>m;
for(i=1;i<=n;i++)
{
if(a==m) sum=sum+1;
else sum=sum+0;
}
cout<<sum<<endl;
return 0;
}
这题巧妙地将需要判断的数放在了较后,使我们必须使用数组进行存储
1104:计算书费
#include<iostream>
#include<cstdio>
using namespace std;
double a[11]={0,28.9,32.7,45.6,78,35,86.2,27.8,43,56,65};//存储书费
int **in()
{
int n,i,x;
double sum=0;
for(i=1;i<=10;i++)
{
cin>>x;
sum=sum+a*x;//计算总书费
}
printf("%.1lf",sum);
return 0;
}
这题利用了数组存储书本的费用,再进行计算,较后输出总钱数即可
1105:数组逆序重存放
#include<iostream>
using namespace std;
int a[101];
int **in()
{
int i,n;
cin>>n;
for(i=1;i<=n;i++) cin>>a;//按照顺序输入
for(i=n;i>=1;i--) cout<<a<<' ';//按照反序输出即可
return 0;
}
这道题使用反序输出即可
1106:年龄与疾病
#include<iostream>
#include<cstdio>
using namespace std;
int a[101];
int **in()
{
int i;
double n,sum1=0,sum2=0,sum3=0,sum4=0,s1=0,s2=0,s3=0,s4=0;
cin>>n;
for(i=1;i<=n;i++) cin>>a;
for(i=1;i<=n;i++)
{
if(a>=0&&a<=18) sum1++;//小于18岁的人数
if(a>=19&&a<=35) sum2++;//大于等于18岁小于36岁的人数
if(a>=36&&a<=60) sum3++;//大于等于36岁小于61岁的人数
if(a>=61) sum4++;//大于等于61岁的人数
}
s1=sum1*(100.0/n);//通过人数和总数计算比例
s2=sum2*(100.0/n);
s3=sum3*(100.0/n);
s4=sum4*(100.0/n);
printf("%.2lf%%\n%.2lf%%\n%.2lf%%\n%.2lf%%\n",s1,s2,s3,s4);
//因为要控制输出数位,所以使用printf
return 0;
}
通过数组存储每个人的年龄,再计算比例并输出即可
1107:校门外的树
#include<iostream>
using namespace std;
bool a[10100];
int **in()
{
int l,m,i,j,x,y,sum=0;
cin>>l>>m;
for(i=1;i<=m;i++)
{
cin>>x>>y;
for(j=x;j<=y;j++) a[j]=true;//将区间内的所有树设置为true
}
for(i=0;i<=l;i++) if(a==false) sum++;//如果没有被移除,将计数器增加
cout<<sum<<endl;
return 0;
}
通过模拟所有树的移除情况,较后计算总数
1108:向量点积计算
#include<iostream>
using namespace std;
int a[1001],b[1001];
int **in()
{
int n,i=1,sum=0;
cin>>n;
for(i=1;i<=n;i++) cin>>a;
for(i=1;i<=n;i++)
{
cin>>b;
sum=sum+a*b;//计算总值
}
cout<<sum<<endl;
return 0;
}
这些题都是将数据储存至数组内再进行操作及计算,只要明白数组工作原理及将变化情况进行有效的管理就能够知道题目如何做了
1109:开关灯
#include<iostream>
#include<cstdio>
using namespace std;
bool a[10000],flag;
int **in()
{
int n,m,j,i;
cin>>n>>m;
for(j=1;j<=m;j++)
{
for(i=1;i<=n;i++)
{
if(i%j==0) a=!a;//如果这个地方需要改变
}
}
for(i=1;i<=n;i++)
{
if(a==true)
{
if(flag) cout<<','<<i;//不是第一次就输出逗号和单个数字
else cout<<i;//第一次只输出单个数字
f=true;//确定是否为第一次
}
}
return 0;
}
与 2036 类似,这里重要的是输出的方法
1110:查找特定的值
#include<iostream>
using namespace std;
int a[10001];
int **in()
{
int x,i,n;
cin>>n;
for(i=1;i<=n;i++) cin>>a;
cin>>x;
for(i=1;i<=n;i++)
{
if(a==x)//在数组中查找对应的值并输出
{
cout<<i<<endl;
break;
}
}
cout<<-1<<endl;//如果没有发现,就输出-1
return 0;
}
很简单,直接过了
1111:不高兴的津津
这道题看起来很复杂,但是其实只需要按照题目的意思,一步一步走,通过模拟题目的意思,就可以得出结果,所以做题最重要的步骤就是思考
#include<iostream>
using namespace std;
int k[7],b[7],s[7];
int **in()
{
int i,j,m=0,**x=-1;
for(i=1;i<=7;i++) cin>>k>>b;
for(i=1;i<=7;i++)
{
if(k+b>8)
{
s=k+b-8;
if(s>**x) **x=s;
m=m+1;
}
}
if(m==0) cout<<0<<endl;
else
for(i=1;i<=7;i++)
{
if(k+b-8==**x)
{
cout<<i<<endl;
return 0;
}
}
return 0;
}
1112:较大值和**小值的差
#include<iostream>
using namespace std;
int a;
int **in()
{
int m,**x=-10000,min=10000,i;
//将较大值设置为**小,将**小值设置为较大,是为了方便
cin>>m;
for(i=1;i<=m;i++)
{
cin>>a;
if(a>**x) **x=a;//找到较大值
if(a<min) min=a;//找到**小值
}
cout<<**x-min<<endl;//输出较大值减**小值
return 0;
}
这道题甚至不需要用到数组进行操作
1113:不与较大数相同的数字之和
#include<iostream>
using namespace std;
int a[10001];
int **in()
{
int n,**x=-100000,sum=0,i;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a;
if(a>**x) **x=a;//找出较大值
}
for(i=1;i<=n;i++) if(a!=**x) sum=sum+a;//加上所有非较大值的数
cout<<sum<<endl;
return 0;
}
这道题可以说是非常简单了
1114:白细胞计数
#include<iostream>
#include<cstdio>
using namespace std;
double a[3001],b[3001];
int **in()
{
int **x1,min1,i;
double **x=-99999,min=99999,x,**x0=-99999,sum=0,n;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a;
if(a>**x)//求较大值
{
**x=a;
**x1=i;
}
if(a<min)//求**小值
{
min=a;
min1=i;
}
sum+=a;
}
x=1.0*(sum-**x-min)/(n-2);//求平均数
for(i=1;i<=n;i++)
{
if(i!=**x1&&i!=min1)
{
b=a-x;
if(b<0) b=-b;
}
else
b=-99999;
}
for(i=1;i<=n;i++) if(b>**x0) **x0=b;
printf("%.2lf %.2lf\n",x,**x0);
return 0;
}
这道题的难点在于有些复杂,需要对每一步的作用进行分析
1115:直方图
#include<iostream>
using namespace std;
int a[10001];
int **in()
{
int **x=-99999,n,x,i;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>x;
a[x]++;//这里应用到了桶计数法
if(x>**x) **x=x;//求较大值
}
for(i=0;i<=**x;i++) cout<<a<<endl;//输出每一段的频数
return 0;
}
桶计数法 : 指利用数组,将每一个数的出现次数放入指定的下标处,以统计每个数的出现次数( 它就像桶一样,有很多个桶,把特定的数值放入桶里 )
例如
1 2 2 1 3 3 2 4 2 1 4 2 2 1 4 2 3 1 2 3 2 4 1 2
这些数字
我们用t[5]来统计这些数出现的频数
t[1]++;
t[2]++;
t[2]++;
t[1]++;
...
t[4]++;
t[1]++;
t[2]++;
较后,我们会发现,我们要查找某一数字(x)出现的次数,我们只需查找t[x]即可
优点:好理解,快
缺点:占用空间大,不能统计负数(可以通过错位安放避免)或较大的数
如何判断是否需要使用桶计数,我们需要判断桶的大小是否合适,如果需要的大小过大,就一定不是桶计数
1116:最长平台
#include<iostream>
using namespace std;
int a[100001];
int **in()
{
int i,**x=-9999,l=1,n;
cin>>n;
a[0]=-1;//防止被判定为一个平台
for(i=1;i<=n;i++)
{
cin>>a;
if(a==a[i-1]) l++;//如果与上一个的值相同,那么它们就是一个平台
else l=1;//否则变回1
if(l>**x) **x=l;//几录较大平台的长度
}
cout<<**x<<endl;//输出
return 0;
}
这道题的难点在于判断平台
1117:整数去重
#include<iostream>
using namespace std;
bool x[5100];//桶
int **in()
{
int i,n,a;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a;
if(!x[a])//如果这里没有输出过,我们就输出它
{
cout<<a<<' ';
x[a]=true;//改为输出过
}
}
return 0;
}
这道题就可以运用我们刚才学习的桶计数方法,因为 a > 10 && a < 5000,数组完全存储的下
1118:铺地毯
#include<iostream>
using namespace std;
int a[10001],b[10001],g[10001],k[10001];
int **in()
{
int x,y,n,i;
cin>>n;
for(i=1;i<=n;i++) cin>>a>>b>>g>>k;
cin>>x>>y;
for(i=n;i>=1;i--)
{
if(x>=a&&x<=a+g&&y>=b&&y<=b+k)
//x,y的坐标大于等于一个地毯的左下角
//x,y的坐标小于等于一个地毯的右上角,即左下角的坐标加上地毯的长和宽
//那么这个点上就有地毯
{
cout<<i<<endl;
return 0;
}
}
cout<<"-1"<<endl;
return 0;
}
这道题乍看上去很像二维数组,但是它可以使用一维数组做的,我们需要判断这个点是否存在于某一地毯的范围之中
1119:矩阵交换行
#include<iostream>
#include<cstdio>
using namespace std;
int a[6][6];
int **in()
{
int i,j,n,m,f;
for(i=1;i<=5;++i) for(j=1;j<=5;++j) cin>>a[j];
cin>>m>>n;
for(i=1;i<=5;++i) swap(a[n],a[m]);//交换m和n行上的每一个点
for(i=1;i<=5;++i)
{
f=0;
for(j=1;j<=5;++j)
{
f++;
if(f==1) cout<<a[j];
else cout<<" "<<a[j];
}
cout<<endl;
}//输出矩阵
return 0;
}
这样对某一行的交换实际上是在考察我们对二维数组的理解
1120:同行列对角线的格
这道题是给出一个点的坐标,要求求出经过此点的四条线上的所有点的坐标 ( 需要按照题目给出的顺序输出 )
#include<iostream>
using namespace std;
int **in()
{
int i,j,n,x,y;
cin>>n>>x>>y;
for(i=1;i<=n;i++) cout<<'('<<x<<','<<i<<") ";//x坐标不变,存在于一条竖线上
cout<<endl;
for(i=1;i<=n;i++) cout<<'('<<i<<','<<y<<") ";//y坐标不变,存在于一条横线上
cout<<endl;
for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(i-x==j-y) cout<<'('<<i<<','<<j<<") ";
//左上到右下的对角线的特点:与给出坐标的对应坐标的差相同
cout<<endl;
for(i=n;i>=1;i--) for(j=n;j>=1;j--) if(i-x==-(j-y)) cout<<'('<<i<<','<<j<<") ";
//左下到右上的对角线的特点:与给出坐标的对应坐标互为相反数
//因为这里是从左下的右上的,所以得从n开始到1进行循环
//*如果从1开始到n进行循环就会与答案的顺序相反
cout<<endl;
return 0;
}
1121:计算矩阵边缘元素之和
这道题的重点是在判断矩阵的边缘
矩阵的边缘有什么特点 ( 这是一个矩阵 ) :
( 1 , 1 ) ( 2 , 1 ) ( 3 , 1 ) ( 4 , 1 )
( 1 , 2 ) ( 2 , 2 ) ( 3 , 2 ) ( 4 , 2 )
( 1 , 3 ) ( 2 , 3 ) ( 3 , 3 ) ( 4 , 3 )
( 1 , 4 ) ( 2 , 4 ) ( 3 , 4 ) ( 4 , 4 )
我们发现矩阵的上边缘和左边缘总会有一个值为 1,而下边缘和右边缘总会有一个值为边长 n
#include<iostream>
using namespace std;
int a[101][101];
int **in()
{
int m,n,i,j,sum=0;
cin>>m>>n;
for(i=1;i<=m;++i)
for(j=1;j<=n;++j)
{
cin>>a[j];
if(i==1||j==1||i==m||j==n) sum+=a[j];
//在某一点上某一坐标为1或边长n和m,就将它的值记录在sum中
}
cout<<sum<<endl;
return 0;
}
1122:计算鞍点
鞍点的定义 : 是所在行的较大值,并且是所在列的**小值
我们将较大值记录下来 ( 因为只有一个较大值,所以我们没有必要记录较大值的位置 )
#include<iostream>
using namespace std;
int a[7][7];
int **in()
{
int i,j,**x,min,point;
bool flag=false;
for(i=1;i<=5;i++)
{
**x=-1;
for(j=1;j<=5;j++)
{
cin>>a[j];
if(a[j]>**x) **x=a[j];//求较大值
}
a[6]=**x;//将较大值记录在所在行的第6个位置
}
for(j=1;j<=5;j++)
{
min=1000000;
for(i=1;i<=5;i++) if(a[j]<min) min=a[j],point=i;//求**小值
if(a[point][6]==min)//如果这个点是鞍点,即上次记录的较大值是本次的**小值
{
cout<<point<<' '<<j<<' '<<min<<endl;//输出鞍点的坐标和值
flag=true;//记录输出过鞍点
}
}
if(!flag) cout<<"not found"<<endl;//如果没有输出过鞍点,则输出"not found"
return 0;
}
1123:图像相似度
这道题很简单,通过计算相同点的个数,在计算占全部点的百分比即可
#include<iostream>
#include<cstdio>
using namespace std;
int a[101][101],b[101][101];
int **in()
{
int i,j,m,n;
double area,same;
cin>>m>>n;
area=m*n;//计算点的总数
for(i=1;i<=m;i++) for(j=1;j<=n;j++) cin>>a[j];//输入第一张图
for(i=1;i<=m;i++) for(j=1;j<=n;j++) cin>>b[j];//输入第二张图
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
if(a[j]==b[j]) same++;//计算相同的个数
}
}
printf("%.2lf\n",100.0/area*same*1.0);//计算百分比并控制位数输出
return 0;
}
1124:矩阵加法
矩阵加法 : 两个数组,将相同位置上的值相加 (即 c=a+b)
#include<iostream>
using namespace std;
int a[101][101],b[101][101];
int **in()
{
int i,j,n,m;
cin>>n>>m;
for(i=1;i<=n;i++) for(j=1;j<=m;j++) cin>>a[j];//输入第一个矩阵
for(i=1;i<=n;i++) for(j=1;j<=m;j++) cin>>b[j];//输入第二个矩阵
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++) cout<<a[j]+b[j]<<' ';//输处两个矩阵相同位置上的和
cout<<endl;
}
return 0;
}
1125:矩阵乘法
矩阵乘法 : 不太好概括...就是下面的公式...
#include<iostream>
using namespace std;
int a[110][110],b[110][110];
int **in()
{
int i,j,k,n,m,x,sum;
cin>>n>>m>>x;
for(i=1;i<=n;i++) for(j=1;j<=m;j++) cin>>a[j];//输入第一个矩阵
for(i=1;i<=m;i++) for(j=1;j<=x;j++) cin>>b[j];//输入第二个矩阵
for(i=1;i<=n;i++)
{
for(j=1;j<=x;j++)//题目给出结果为n*k
{
sum=0;
for(k=1;k<=m;k++) sum+=a[k]*b[k][j];//按照矩阵乘法的公式求和
//因为我们的数组是从1开始而非从0开始,所以这里也是从1开始的
cout<<sum<<' ';//输出结果
}
cout<<endl;
}
return 0;
}
1126:矩阵转置
#include<iostream>
using namespace std;
int a[101][101];
int **in()
{
int m,n,i,j;
cin>>n>>m;
for(i=1;i<=n;i++) for(j=1;j<=m;j++) cin>>a[j];//输入矩阵
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++) cout<<a[j]<<' ';//矩阵转置的方法,将i和j的位置调换即可
cout<<endl;
}
return 0;
}
知道如何转置矩阵即可完成
1127:图像旋转
#include<iostream>
using namespace std;
int a[101][101];
int **in()
{
int m,n,i,j;
cin>>n>>m;
for(i=1;i<=n;i++) for(j=1;j<=m;j++) cin>>a[j];
for(i=1;i<=m;i++)
{
for(j=n;j>=1;j--) cout<<a[j]<<' ';//新的转置方法
cout<<endl;
}
return 0;
}
同上...( 真不是我懒得写 )
1128:图像模糊处理
#include<iostream>
#include<c**th>
using namespace std;
int a[110][110],b[110][110];
int **in()
{
int i,j,m,n;
cin>>n>>m;
for(i=1;i<=n;i++) for(j=1;j<=m;j++) cin>>a[j];//输入
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(i==1||i==n||j==1||j==m) b[j]=a[j];
//如果是周围一圈,就不改变
else b[j]=round((a[j]+a[i-1][j]+a[i+1][j]+a[j-1]+a[j+1])/5.0);
//如果是不是周围一圈,就将自己以及周围四个像素点
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++) cout<<b[j]<<' ';//输出
cout<<endl;
}
return 0;
}
用到了刚刚学习的判断周围的方法
1129:统计数字字符个数
#include<iostream>
#include<string>
using namespace std;
string a;
int **in()
{
getline(cin,a);
int i,l=a.szie(),sum=0;
for(i=0;i<l;i++) if(a>='0'&&a<='9') sum++;//发现数字字符并统计
cout<<sum<<endl;
return 0;
}
这道题将每一位进行处理,如果发现是数字字符的话就使计数器增加即可
1130:找第一个只出现一次的字符
这道题可以进行桶计数,因为数量较少,只有小写字母
#include<iostream>
#include<string>
using namespace std;
int t[27];//只有26个小写字母,可以进行桶计数
string a;
int **in()
{
getline(cin,a);
int i,n,l=a.size();
for(i=0;i<l;i++) t[a-'a']++;//利用桶进行统计出现次数
for(i=0;i<l;i++)
{
if(t[a-'a']==1)//如果这个小写字母出现的次数为1
{
cout<<a<<endl;//输出
return 0;
}
}
cout<<"no"<<endl;//没有则输出"no"
return 0;
}
1131:基因相关性
这道题是统计相同值并计算百分比并判断大小是否大于给定值即可
#include<iostream>
#include<string>
using namespace std;
string a,b;
int **in()
{
double n,l,sum=0;
int i;
cin>>n;
getchar();//在cin后使用getline必须要加上一个getchar过滤回车
getline(cin,a);//读入a字符串
getline(cin,b);//读入b字符串
l=a.size();
for(i=0;i<l;i++) if(a==b) sum++;//如果相同则使sum增加
if(sum/l*1.0>=n) cout<<"yes"<<endl;//如果sum的值大于给定值n,输出"yes"
else cout<<"no"<<endl;//否则输出"no"
return 0;
}
1132:石头剪子布
这道题需要明白如何在字符串中进行判断
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
string a,b;
int **in()
{
int n,i,l;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a>>b;
if(a[0]==b[0]) cout<<"Tie"<<endl;//如果相同则平局
else
if((a[0]=='R'&&b[0]=='S')||(a[0]=='S'&&b[0]=='P')||(a[0]=='P'&&b[0]=='R'))
//不是平局则是一方胜利,如果玩家1可以打败玩家2,则玩家1胜利
{
cout<<"Player1"<<endl;
}
else cout<<"Player2"<<endl;//否则就是玩家2胜利
}
return 0;
}
1133:输出亲朋字符串
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
string a;
int b[99999];
int **in()
{
int n,i,l;
getline(cin,a);
l=a.size();
for(i=0;i<l;i++)
{
if(i!=l-1) b=a+a[i+1];//不是较后一个
else b=a+a[0];//较后一个
}
for(i=0;i<l;i++) cout<<char(b);//输出,需要进行强制转换数据类型
return 0;
}
按照题目进行模拟即可
1134:合法C标识符查
C语言标识符的要求为 :
非保留字
只包含字母,数字以及下划线
不以数字开头
而题目保证一定不为保留字 ( 毕竟我们不可能去自己判断吧... )
所以我们只需判断后两个即可
#include<iostream>
#include<string>
using namespace std;
string a;
int **in()
{
int i,l;
getline(cin,a);
l=a.size();
for(i=0;i<l;i++)
{
if((a[0]>='A'&&a[0]<='Z')||(a[0]>='a'&&a[0]<='z')||a[0]=='_')
{
if(!((a>='A'&&a<='Z')||(a>='a'&&a<='z')||(a>='0'&&a<='9')||a=='_'))
{
cout<<"no"<<endl;
return 0;
}
}
else
{
cout<<"no"<<endl;
return 0;
}
}
cout<<"yes"<<endl;
return 0;
}
只需进行简单的判断即可
1135:配对碱基链
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
string a;
int **in()
{
int i,l;
getline(cin,a);
l=a.size();
for(i=0;i<l;i++)
{
if(a=='A') cout<<'T';//遇到对应的字符就输出对应的字符
if(a=='T') cout<<'A';
if(a=='C') cout<<'G';
if(a=='G') cout<<'C';
}
return 0;
}
很简单,过
1136:密码翻译
这道题是十分简单的凯撒密码,通过对每一个字符的移位进行加密操作
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
string a;
int **in()
{
int i,l;
getline(cin,a);
l=a.size();
for(i=0;i<l;i++)
{
if(a=='z'||a=='Z') a=a-25;
else
if((a>='a'&&a<='y')||(a>='A'&&a<='Y')) a=a+1;
//简单的移位
}
cout<<a;
return 0;
}
1137:加密的病历单
这道题是上一道题的升级版,需要我们进行多个改变,按照题目的意思去做就不会难了
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
string a;
int **in()
{
int i,l;
getline(cin,a);
l=a.size();
for(i=0;i<l;i++)
{
if((a>='x'&&a<='z')||(a>='X'&&a<='Z')) a=a-23;
else
if((a>='a'&&a<='w')||(a>='A'&&a<='W')) a=a+3;
else if(a>='a'&&a<='z') a=a-32;
else a=a+32;
//进行对应的改变
}
for(i=l-1;i>=0;i--) cout<<a;
return 0;
}
1138:将字符串中的小写字母转换成大写字母
这道题就更加简单了,只需改变大小写即可
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
string a;
int **in()
{
int i,l,n;
getline(cin,a);
l=a.size();
for(i=0;i<l;i++)
{
if((a>='a'&&a<='z')) cout<<(char)(a-32);//将小写字母改为大写字母
else cout<<a;//否则直接输出即可
}
return 0;
}
1139:整理药名
这道题只需改变第一位为大写字母,将后面的字母改为小写字母即可
#include<iostream>
#include<iostream>
#include<cstring>
using namespace std;
char a[25];
int **in()
{
int n,l,i,j;
cin>>n;
for(i=0;i<n;i++)
{
cin>>a;//输入药品名
if(a[0]>='a'&&a[0]<='z') a[0]=a[0]-32;//改变第一位
l=strlen(a);
for(j=1;j<l;j++) if(a[j]>='A'&&a[j]<='Z') a[j]=a[j]+32;
//改变后续的位数
cout<<a<<endl;//输出
}
return 0;
}
1140:验证子串
利用 string 类型中内置的函数进行验证子串偷懒
#include<iostream>
#include<string>
using namespace std;
string a,b;
int **in()
{
int i,l,l2;
getline(cin,a);
l=a.size();
getline(cin,b);
l2=b.size();
if(l>=l2)
{
if(a.find(b)!=-1)
{
cout<<b<<" is substring of "<<a<<endl;
return 0;
}
else
cout<<"No substring"<<endl;
return 0;
}
else
if(l<l2)
{
if(b.find(a)!=-1)
{
cout<<a<<" is substring of "<<b<<endl;
return 0;
}
else
cout<<"No substring"<<endl;
return 0;
}
}
1141:删除单词后缀
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
char a[33];
int **in()
{
int i,l;
cin>>a;
l=strlen(a);
if((a[l-1]=='r'&&a[l-2]=='e')||(a[l-1]=='y'&&a[l-2]=='l'))
{
for(i=0;i<l-2;i++) cout<<a;//分别判断并输出
}
else
if(a[l-1]=='g'&&a[l-2]=='n'&&a[l-3]=='i')
{
for(i=0;i<l-3;i++) cout<<a;
}
return 0;
}
找到指定的后缀并删除再输出即可
1142:单词的长度
找到所有单词并计算长度再输出即可
#include<iostream>
#include<cstring>
using namespace std;
char a[34];
int **in()
{
int i,l,sum=0,k=0;
gets(a);
l=strlen(a);
a[l]=' ';
for(i=0;i<=l;i++)
{
if(a!=' ') sum++;
if(a==' '||a=='\0')//'\0'是结束符,可以用于判断是否结束
{
k=k+1;
if(sum!=0)
{
if(k==1) cout<<sum;
else if(k>1) cout<<','<<sum;
sum=0;
}
}
}
return 0;
}
1143:最长最短单词
#include<iostream>
#include<cstring>
char a[40000];
using namespace std;
int **in()
{
int i,l,sum=0,**x=0,min=101,x,y;
gets(a);
l=strlen(a);
a[l]=' ';
for(i=0;i<=l;i++)
{
if((a!=' ')&&(a!=',')) sum++;
else
if(sum>0)
{
if(sum>**x)//计算最长
{
**x=sum;
x=i-sum;
}
if(sum<min)//计算最短
{
min=sum;
y=i-sum;
}
sum=0;
}
}
for(i=x;i<=**x+x-1;i++) cout<<a;//输出
cout<<endl;
for(i=y;i<=min+y-1;i++) cout<<a;//输出
return 0;
}
找出最长最短并记录它们的位置再输出即可
1144:单词翻转
#include<iostream>
#include<cstring>
using namespace std;
char a[1000];
int **in()
{
int l,j,i,sum=0,k;
gets(a);
l=strlen(a);
a[l]=' ';
for(i=0;i<=l;i++)
{
if(a!=' ') sum++;
else
{
k=i;
for(j=1;j<=sum;j++) cout<<a[--k];//找到每一个单词并逆序输出
sum=0;
if(i!=l) cout<<" ";//遇到空格输出
}
}
cout<<endl;
return 0;
}
这道题值得注意的是它是对每一个单词进行反转而不是对一个句子进行反转
1145:字符串p型编码
题就是变相考察了对字符串每个字符的数量统计
#include<iostream>
#include<string>
char a[1001];
using namespace std;
int **in()
{
int i,l,sum=1;
gets(a);
l=strlen(a);
for(i=0;i<l;i++)
{
if(a!=a[i+1])//判断是否应该继续统计个数
{
cout<<sum<<a;//输出个数和字符即可
sum=1;//重置
}
else sum++;
}
return 0;
}
1146:判断字符串是否为回文
#include<iostream>
#include<cstring>
using namespace std;
char a[101];
int **in()
{
gets(a);
int i=strlen(a)-1,j=0;
while((j<i)&&(a[j]==a)) i--,j++;//如果在两边都相同的情况下就使两端靠近
if(j>=i) cout<<"yes"<<endl;//如果两个变量挨在了一起,就说明这是回文
else cout<<"no"<<endl;//否则就不是
return 0;
}
这里使用的方法非常巧妙,一下子也许理解不了,多加思考即可
1147:较高分数的学生姓名
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
string a,m;
int **in()
{
int i,n,**x=-1,x;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>x>>a;
if(**x<x)//找到了目前的较高分
{
**x=x;//重置较高分
m=a;//重置较高分的人的名字
}
}
cout<<m;//输出
return 0;
}
很简单,过
1148:连续出现的字符
#include<iostream>
#include<cstring>
using namespace std;
char a[2500];
int **in()
{
int i,n,l,sum=0;
cin>>n>>a;
l=strlen(a);
for(i=0;i<l;i++)
{
if(sum==n)//第一个达到了n次
{
cout<<a;//输出
return 0;
}
if(a==a[i+1]) sum++;//相等时就增加
else sum=1;//否则变回1
}
cout<<"No"<<endl;//没有则输出"No"
return 0;
}
统计连续出现的字符,达到则输出即可
1149:最长单词2
#include<iostream>
#include<cstring>
using namespace std;
char a[500];
int **in()
{
int i,l,**x=-1,s,sum=0;
gets(a);
l=strlen(a);
for(i=0;i<l;i++)
{
if(a!=' '&&a!='.') sum++;
else
if(sum>0)
{
if(sum>**x)
{
**x=sum;//记录单词的长度
s=i-sum;//记录单词的起始点
}
sum=0;
}
}
for(i=s;i<s+**x;i++) cout<<a;//输出单词
return 0;
}
这道题需要我们输出单词,我们只需记录单词的起始点以及长度就可以输出了
1839:【05NOIP提高组】谁拿了最多奖学金
这题需要判断各种选项是否符合并累加结果,较后记录即可
#include<iostream>
using namespace std;
string name,bestname;//人名,奖学金较高的人的名字
int **rk,opinion,num;//分数,班级评价分数,论文数
bool leader,west;//学生干部,西部学生
char x,y;
int **in()
{
int i,n,money,sum=0,**xn=-1;
cin>>n;
for(i=1;i<=n;i++)
{
money=0;//初始化money
cin>>name>>**rk>>opinion>>x>>y>>num;//输入
leader=(x=='Y'?true:false);//学生干部
west=(y=='Y'?true:false);//西部学生
if(**rk>80&&num>0) money+=8000;//院士奖学金
if(**rk>85&&opinion>80) money+=4000;//五四奖学金
if(**rk>90) money+=2000;//成绩优秀奖
if(**rk>85&&west) money+=1000;//西部奖学金
if(opinion>80&&leader) money+=850;//班级贡献奖
sum+=money;//计算总和
if(money>**xn) **xn=money,bestname=name;//更新较大值和奖学金最多的人
}
cout<<bestname<<endl<<**xn<<endl<<sum<<endl;//输出
return 0;
}
十分的简单的对吧
文档下载
转载:感谢您阅览,转载请注明文章出处“来源从小爱孤峰知识网:一个分享知识和生活随笔记录的知识小站”。
链接:C++ 数组一本通平台讲解http://www.gufeng7.com/niaolang/1850.html
联系:如果侵犯了你的权益请来信告知我们删除。邮箱:119882116@qq.com
上一篇: C++ 数组讲解
下一篇: C++ 函数讲解与一本通平台讲解