总结
如果出现非满分(80,90),则考虑边界问题,理解题意问题,样例说明问题。以分蛋糕为例
编译环境为C++11
流程:
1、仔细读题
参数初始化:类型是int还是double,值为0还是数组首元素
如何遍历:由行到列 OR 由列到行,
遍历条件:起始和终止位置
数据更新:覆盖OR开辟
如何计算:手算一遍,写计算式
几个标记元素:由题目得出,特殊的循环遍历方式会用到
2、例子特殊元素,边界问题
3、草稿演算
4、出现运行错误,则检查数组是否越界,数组大小是否正确,循环是否正确(是否出现死循环,循环的条件范围是否正确)
5、出现错误,则检查思路,或者数组太小
6、本地测试样例时,结果和题目要求不同时可以少测一组数据
题目要求: 少测一组:
可以得出本地程序少考虑了哪种情况
7、数组空间往大了开
8、const int MAX=0x3f3f3f3f初始化无穷大
9、比较复杂的判断时可以写函数,例如(仓库规划)
10、谨慎使用continue,break,&&(可以改写成if括号体内写if{}),||
11、90分(非满分时)可以重新梳理一遍,也就是一句一句复杂到main函数里
字符(char)转整数(int)
char c = '6'; //字符型 c = '6'
int num = c - '0'; //转换结果:num = 6
整数(int)转字符(char)
int num = 5; //整型 num = 5
char c = num + '0'; //转换结果:字符型 c = '5'
字符串(string)转整数(int)
#include <cstring> //需要引入cstring头文件
string = "123456"
int n = stoi(str); //转换为整型 n = 123456(转换失败时发生异常)
int n = atoi(str); //转换为整型 n = 123456(转换失败时返回0)
string = "123456.123"
double d = stof(str); //转换为浮点数 d = 123456.123(转换失败时发生异常)
double d = atof(str); //转换为浮点数 d = 123456.123(转换失败时返回0)
整数(int)转字符串(string)
#include <string> //需要引入string头文件
//基本数据类型均可转换
int num = 123456
string str = to_string(num); //转换为字符串 str = "123456"
跳出两层循环
bool flag = true;
for (int i = 0; i < 5 && flag == true; i++)
{
for (int j = 0; j < 5 && flag == true; j++)
{
cout << "i = " << i << " j = " << j << endl;
if (i == 3 && j == 5)
flag = false;
}
}
第一题
仓库规划 (90分一次)
//写一个判断是否比它大的函数
//写一个按行到列的遍历
//二维数组存储
#include<iostream>
using namespace std;
int n,m;//行,列
int arr[2020][2020];
void fun(int h){
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++){
if(arr[h][j]>=arr[i][j]){
break;
}
if(j==m-1){
cout<<i<<endl;
return ;
}
}
if(i==n){
cout<<0<<endl;
}
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++){
arr[i][j]=0;
cin>>arr[i][j];
}
}
for(int i=1;i<=n;i++){
fun(i);
}
return 0;
}
90分:不清楚原因(一下是第二遍得90分后修改的满分)
#include<iostream>
using namespace std;
int arr[2010][2010]={0};
int n,m;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>arr[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(j!=i){
for(int k=1;k<=m;k++){
if(k==m){
if(arr[j][k]>arr[i][k]){
cout<<j<<endl;
j=n+1;
}
}
if(arr[j][k]<=arr[i][k]){
break;
}
}
}
if(j==n){
cout<<0<<endl;
}
}
}
return 0;
}
坐标变换(其一)(秒杀)
//将每个操作数的每一列都加起来
//遍历起始点
//二维数组储存,操作数n为行,2为列 ;起始点m为行,2为列
#include<iostream>
using namespace std;
int n,m;
int l=0;//操作数x(左边一列)之和
int r=0;//操作数y(右边一列)之和
int arr[2020][2020];//操作数
int Arr[2020][2020];//起始点
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
for(int j=0;j<2;j++){
cin>>arr[i][j];
}
}
for(int i=0;i<m;i++){
for(int j=0;j<2;j++){
cin>>Arr[i][j];
}
}
for(int i=0;i<2;i++){
for(int j=0;j<n;j++){
if(i==0){
l+=arr[j][i];
}
if(i==1){
r+=arr[j][i];
}
}
}
for(int i=0;i<m;i++){
for(int j=0;j<2;j++){
if(j==0){
Arr[i][j]+=l;
}
if(j==1){
Arr[i][j]+=r;
}
}
}
for(int i=0;i<m;i++){
for(int j=0;j<2;j++){
cout<<Arr[i][j]<<" ";
if(j==1){
cout<<endl;
}
}
}
return 0;
}
总结:非常愚蠢的方法
忘记cin>>n>>m(?)
第二遍:
#include<iostream>
using namespace std;
int n,m;
int dx,dy;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
int left,right;
cin>>left>>right;
dx+=left;
dy+=right;
}
for(int j=1;j<=m;j++){
int x,y;
cin>>x>>y;
cout<<dx+x<<" "<<dy+y<<endl;
}
return 0;
}
重复局面(秒杀)(保存数据时注意)
//字符串数组储存
//整数数组储存答案
//遍历判断是否相同,相同则整数数组对应位+1
#include<iostream>
using namespace std;
int n;
string str[2020];//字符串数组
int ans[2020];
int main(){
cin>>n;
for(int i=1;i<=n;i++){
ans[i]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=64;j++){
char c;
cin>>c;
str[i]+=c;//字符连接成字符串
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){//核心j<=i;不是遍历每个元素,而是逐渐累加遍历
if(i==j){
continue;
}
if(str[i]==str[j]){
ans[i]++;
}
}
}
for(int i=1;i<=n;i++){//将i<=n写成i<=8
cout<<ans[i]<<endl;
}
return 0;
} //从Dev复制到答题界面时忘记复制}导致编译出错
总结:1、如何定义一个字符串数组
2、如何将字符连接成字符串
3、核心j<=i;不是遍历每个元素,而是逐渐累加遍历
4、将i<=n写成i<=8导致0分(愚蠢)
5、从Dev复制到答题界面时忘记复制 } 导致编译出错
第二遍:
#include<iostream>
using namespace std;
string C[200];
char c;
int n;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=64;j++){
cin>>c;
C[i]+=c;
}
}
for(int i=1;i<=n;i++){
int ans=1;
for(int j=1;j<i;j++){
if(C[i]==C[j]){
ans++;
}
}
cout<<ans<<endl;
}
return 0;
}
田地丈量(秒杀)
//四个一维数组储存点坐标
//int ans+=面积
//竖着遍历(从左上到左下再到右上然后右下)
//x2-x1=x,y2-y1=y最后 x*y算出面积
#include<iostream>
using namespace std;
int x1[2020],y1[2020],x2[2020],y2[2020];
int ans;
int n,a,b;//n块地,(a,b)右上坐标
int main(){
cin>>n>>a>>b;
for(int i=1;i<=n;i++){
for(int j=1;j<=4;j++){
if(j==1){
cin>>x1[i];
}
if(j==2){
cin>>y1[i];
}
if(j==3){
cin>>x2[i];
}
if(j==4){
cin>>y2[i];
}
}
}
for(int i=1;i<=n;i++){
if(x1[i]>a){
x1[i]=a;
}else if(x1[i]<0){
x1[i]=0;
}
if(y1[i]>b){
y1[i]=b;
}else if(y1[i]<0){
y1[i]=0;
}
if(x2[i]>a){
x2[i]=a;
}else if(x2[i]<0){
x2[i]=0;
}
if(y2[i]>b){
y2[i]=b;
}else if(y2[i]<0){
y2[i]=0;
}
}
for(int i=1;i<=n;i++){
ans+=(x2[i]-x1[i])*(y2[i]-y1[i]);
}
cout<<ans;
return 0;
}
总结:忘记cout<<ans
思路:如何存数据、如何处理数据到新的地方还是覆盖、如何遍历、如何求结果。
第二遍:
#include<iostream>
using namespace std;
int x1[110],y1[110],x2[110],y2[110];
int n;
int r,up;
int ans;
int main(){
cin>>n;
cin>>r>>up;
for(int i=1;i<=n;i++){
cin>>x1[i]>>y1[i]>>x2[i]>>y2[i];
if(x1[i]<0){
x1[i]=0;
}else if(x1[i]>r){
x1[i]=r;
}
if(y1[i]<0){
y1[i]=0;
}else if(y1[i]>up){
y1[i]=up;
}
if(x2[i]<0){
x2[i]=0;
}else if(x2[i]>r){
x2[i]=r;
}
if(y2[i]<0){
y2[i]=0;
}else if(y2[i]>up){
y2[i]=up;
}
ans+=(x2[i]-x1[i])*(y2[i]-y1[i]);
}
cout<<ans;
return 0;
}
现值计算 (秒杀)
//int n,double i分别表示年数和银行年利率
// double num【2020】//每年的收支
//覆盖数据
//公式分别计算每年的当前价值
//double ans+=每年的当前价值
#include<iostream>
using namespace std;
int n;
double i,ans;
int count[2020];
double num[2020];
int main(){
cin>>n>>i;
for(int j=0;j<=n;j++){
cin>>num[j];
}
for(int k=1;k<=n;k++){
for(int l=1;l<=k;l++){
num[k]=num[k]/(1+i);//核心:第一年需要除一次,第二年需要除两次,依次累加
}
}
for(int m=0;m<=n;m++){
ans+=num[m];
}
cout<<ans;
return 0;
}
总结:理解不清题意时,需要模拟手算一遍数据,慢慢看题,寻找规律。
第一遍思路计算:-200*(1+0.05)*(1+0.05)+100/(1+0.05)+100/1
第二遍思路计算:-200 +100/(1+0.05)+ 100 /(1+0.05)/(1+0.05)
其实-200不用动
第二遍:
#include<iostream>
using namespace std;
double n,m;
double ans;
int main(){
cin>>n>>m;
cin>>ans;
for(int i=1;i<=n;i++){
double flag;
cin>>flag;
for(int j=1;j<=i;j++){
flag=flag/(1+m);
}
ans+=flag;
}
cout<<ans;
return 0;
}
如此编码(秒杀,演算一遍过)
//int n,m分别表示题目数量和数字
//int ans[2020]答案数组,顺序输出
//int ai[2020],bi[2020],ci[2020]
//找最优值循环(核心);类似背包问题
#include<iostream>
using namespace std;
int n,m;
int ans[2020];
int ai[2020],bi[2020],ci[2020];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>ai[i];
}
ci[1]=1;
for(int i=2;i<=n;i++){
ci[i]=ci[i-1]*ai[i-1];
}
for(int i=n;i>=1;i--){
bi[i]=m/ci[i];//核心:小数学问题
m=m-bi[i]*ci[i];
}
for(int i=1;i<=n;i++){
cout<<bi[i]<<" ";
}
return 0;
}
总结:每次都写成
for(int i=7;i>=1;i--){
bi[i]=m/ci[i];//核心:小数学问题
m=m-bi[i]*ci[i];
}
而不是
for(int i=n;i>=1;i--){
bi[i]=m/ci[i];//核心:小数学问题
m=m-bi[i]*ci[i];
}
应该注意循环内的条件
第二遍:
#include<iostream>
using namespace std;
int n,m;
int a[30];
long c[30];
long ans[30];
int main(){
cin>>n>>m;
c[1]=1;
for(int i=1;i<=n;i++){
cin>>a[i];
if(i!=1){
c[i]=c[i-1]*a[i-1];
}
}
for(int i=n;i>=1;i--){
if(m>=c[i]){
ans[i]=m/c[i];
m=m-ans[i]*c[i];
}
}
for(int i=1;i<=n;i++){
cout<<ans[i]<<" ";
}
return 0;
}
归一化处理(秒杀)(数组开小了导致90分一次)
//整数数组储存
//方差数组
//答案数组
//一个for循环遍历
//带入公式计算放入答案数组
//double类型
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int n;//n个数
double Number[2020];//初始值
double average;//平均数
double var;//方差
double ans[2020];//答案
double sum=0;//求和除以n得平均数
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>Number[i];
sum+=Number[i];
}
average=sum/n;
sum=0;
for(int i=1;i<=n;i++){
sum+=(Number[i]-average)*(Number[i]-average);
}
var=sum/n;
for(int i=1;i<=n;i++){
Number[i]=(Number[i]-average)/(sqrt(var));
cout<<Number[i]<<endl;
}
return 0;
}
第二遍
#include<iostream>
#include<cmath>
using namespace std;
int n;
double arr[1010];
double pj;
double fc;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>arr[i];
pj+=arr[i];
}
pj=pj/n;
for(int i=1;i<=n;i++){
fc+=(arr[i]-pj)*(arr[i]-pj);
}
fc=fc/n;
for(int i=1;i<=n;i++){
double ans=(arr[i]-pj)/sqrt(fc);
printf("%f ",ans);
}
return 0;
}
总结:double类型而不是int类型(第一遍上来直接写了int)
未初始化警告(注意看题)(学会调试数据)
标记数组形式:
//int n,k分别表示变量的数量和赋值语句的条数
//一个标记数组
//一个答案ans
//一个for循环,k为限制
#include<iostream>
using namespace std;
int n,k;
int ans=0;
bool flag[100020];
int main(){
cin>>n>>k;
for(int i=1;i<=k;i++){
int l=0;//左边值
int r=0;//右边值
cin>>l>>r;
if(r==0){
flag[l]=true;
continue;//考虑常量0
}
if(flag[r]==false){//注意顺序
ans=ans+1;
}
flag[l]=true;
}
cout<<ans;
return 0;
}
key-value形式:
#include<iostream>
using namespace std;
int ans=0;
int arr[100010][1]={0};
int n;
int count;
int main(){
cin>>n>>count;
for(int i=1;i<=count;i++){
int left;
int right;
cin>>left>>right;
if(right==0){
arr[left][0]++;
if(i!=count){
continue;
}
}
if(right!=0&&arr[right][0]==0){
ans++;
arr[left][0]++;
}else{
arr[left][0]++;
}
}
cout<<ans;
return 0;
}
总结:考虑问题不全面(没考虑常量0),导致结果比预期多1
问题:出现运行错误
解决:数组越界,数组开太小,题目要求10的5次方,则应该开100000
注意看题
注意考虑判断条件的顺序
序列查询(一遍过,但有心理压力)
总结:
第一遍犯病: 最后一个为0的
解决:缺少一个边界条件去判断如果i大于序列的最后一个数时,f(i)= n
出现超时:不看子任务要求和提示(即不完整理解题意)
解决:看提示
轻敌:解决:仔细看题,演算一遍
单个例子正确,不能AC:解决:循环条件,循环体的参数不对
错误代码:
#include<iostream>
using namespace std;
int n,N;
int num[2020];
int flag;
int index=1;
int ans;
int count;
int main(){
cin>>n>>N;
num[0]=0;
for(int i=1;i<=n;i++){
cin>>num[i];
}
for(int i=0;i<N;i++){
if(i==num[index]){
ans+=(i-flag)*num[flag];//参数不对,计算式不对
index++;
flag=i;
count++;
}
if(i==N-1){
ans+=(i-flag+1)*num[flag];//参数不对 ,计算式不对
}
}
cout<<ans;
return 0;
}
没有思路,不知道如何循环遍历:解决设置标记参数;如flag,index,count
AC代码:
//int n,N 数组里有n个数,for从0到N遍历
//int num【】数组
//int flag作为标记,ans+=(N-flag)*num【flag】,flag=N
//int index当遍历数等于数组数时index++
#include<iostream>
using namespace std;
int n,N;
int num[2020];
int flag;
int index=1;
int ans;
int count;
int main(){
cin>>n>>N;
num[0]=0;
for(int i=1;i<=n;i++){
cin>>num[i];
}
for(int i=0;i<N;i++){
if(i==num[index]){
ans+=(i-flag)*count;
index++;
flag=i;
count++;
}
if(i==N-1){
ans+=(i-flag+1)*count;
}
}
cout<<ans;
return 0;
}
第二遍:
#include<iostream>
using namespace std;
int n,N;
int arr[500]={0};
int index=1;
int flag=0;
int count=0;
int ans=0;
int main(){
cin>>n>>N;
for(int i=1;i<=n;i++){
cin>>arr[i];
}
for(int j=1;j<N;j++){
if(j==arr[index]){
ans+=(j-flag)*count;
index++;
count++;
flag=j;
}
if(index>n){
ans+=((N-1)-flag+1)*count;
j=N;
}
}
cout<<ans;
return 0;
}
数组推导(小卡)
//int n,n个数
//int num[100010]存数
//int max记录最大前缀
//int smax,smin答案:最大最小值
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int n;
int num[100010];
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>num[i];
}
int max=num[0];//初始值(关键)
int smax=num[0];
int smin=num[0];
for(int i=1;i<=n-1;i++){
if(num[i]<=max){
smax=smax+max;
}else {
smax+=num[i];
smin+=num[i];
max=num[i];
}
}
cout<<smax<<endl<<smin;
return 0;
}
参数初始化错误:
原因:先入为主的认定例子中的数据(照着例子写程序)
解决:提交结果为错误时,思考特殊元素,边界问题
灰度直方图(秒杀)
#include<iostream>
using namespace std;
int n,m;
int L;
int num;
int ans[2020];
int main(){
cin>>n>>m>>L;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
int k=0;
cin>>num;
k=num;
ans[k]++;
}
}
for(int i=0;i<L;i++){
cout<<ans[i]<<" ";
}
return 0;
}
期末预测之安全指数(秒杀)
#include<iostream>
using namespace std;
int n;
int ans;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int left=0;
int right=0;
cin>>left>>right;
ans=ans+left*right;
}
if(ans<=0){
cout<<0;
}else{
cout<<ans;
}
return 0;
}
称检测点查询(小卡)
碰到一些如果没有遍历到结果就输出某一值会卡顿
比如这题:假如数组里都为1(距离都相同),则我们应该输出前三位(输出序号最小的):1 2 3
如仓库规划:如果仓库 i 没有上级,则输出0。
解决:在数组遍历完后加一循环或者判断找答案。
线性分类器(卡住了,可重做)(练习vector)
解题思路
容易想到只要把点的坐标带入方程看结果与0的大小可以判断出点在直线左侧还是右侧。
对于每一个方程(直线),判断的过程如下:
记录下每个点的信息(包括哪一类),判断的时候先计算第一个点位于直线左边还是右边,然后看剩余的点是否和第一个点同类别:
如果同类别,那么该点应该和第一个点在直线同一边
如果不同类别,那么该点应该和第一个点分处于直线两侧
注意点
题目中提到方程的三个参数的绝对值 <=10^6,那么把点代入的过程中即源代码中的第13和16行处的r , r e s r, resr,res需要用long long型。
如果写成int型,测评结果为0分。
#include<iostream>
using namespace std;
const int maxn = 1010;
int n, m;
struct point{
int x, y;
bool flag; // A类为true,B类为false
}points[maxn];
int a, b, c; // 方程的三个参数
bool solve(){
// 用第一个点区分A类,B类在直线的哪一边
long long r = a+b*points[0].x+c*points[0].y;
for(int i=1; i<n; i++){
long long res = a+b*points[i].x+c*points[i].y;
if(points[i].flag == points[0].flag){
// 和第一个点同类别
if(r*res < 0)
return false; // 异号,同类的点不在直线同一边
}
else{
// 和第二个点不同类别
if(r*res > 0)
return false; // 同号,不同类的点在直线同一边
}
}
return true;
}
int main(){
cin>>n>>m;
int x, y;
char type;
for(int i=0; i<n; i++){
cin>>points[i].x>>points[i].y>>type;
if(type == 'A'){
points[i].flag = true;
}
else
points[i].flag = false;
}
for(int i=0; i<m; i++){
cin>>a>>b>>c;
if(solve()){
printf("Yes\n");
}
else{
printf("No\n");
}
}
return 0;
}
字符A是17
1、储存类型为结构体
2、以第一个点的符号正负,类型为标记
3、写出确切的解题思路,过程
第二遍(vector版)
#include<iostream>
#include<vector>
using namespace std;
int n,m;
int arr[1010][1010];
char type[1010];
vector<char> Left;
vector<char> Right;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>arr[i][0]>>arr[i][1]>>type[i];
}
for(int j=1;j<=m;j++){
int o1,o2,o3;
cin>>o1>>o2>>o3;
Left.clear();
Right.clear();
for(int k=1;k<=n;k++){
if(o1+arr[k][0]*o2+arr[k][1]*o3<0){
Left.push_back(type[k]);
}
if(o1+arr[k][0]*o2+arr[k][1]*o3>0){
Right.push_back(type[k]);
}
}
bool isLeftSame = true;
for (int l = 1; l < Left.size(); l++) {
if (Left[l] != Left[l - 1]) {
isLeftSame = false;
break;
}
}
bool isRightSame = true;
for (int l = 1; l < Right.size(); l++) {
if (Right[l] != Right[l - 1]) {
isRightSame = false;
break;
}
}
if (isLeftSame && isRightSame) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
}
return 0;
}
报数
出现的问题:两个样例都通过,答案却只有80分
解决:
边界问题:将while(i!=count)改成while(i!=count+1)
//写一个判断是不是7的倍数,含不含有7,有则返回false
//int ans[4]作为答案
//循环条件:while(i!=count)
#include<iostream>
using namespace std;
int ans[4]={0,0,0,0};
int i=1;
int count=0;
bool judge(int i){
if(i%7==0){
return true;
}
while(i!=0){
int flag=i%10;
if(flag==7){
return true;
}
i=i/10;
}
return false;
}
int main(){
cin>>count;
while(i!=count+1){
if(i%4==1&&judge(i)){
ans[0]++;
count++;
}else if(i%4==2&&judge(i)){
ans[1]++;
count++;
}else if(i%4==3&&judge(i)){
ans[2]++;
count++;
}else if(i%4==0&&judge(i)){
ans[3]++;
count++;
}
i++;
}
for(int i=0;i<4;i++){
cout<<ans[i]<<endl;
}
return 0;
}
小明种苹果(秒杀)(答案与序号和数相关)
//遍历二维数据全部元素相加为第一个答案
//行号为第二个答案,比较右边最大的数为第三个答案
#include<iostream>
#include<cmath>
using namespace std;
int n,m;
int arr[1010][1010];
int a1=0;
int num[1010]={0};
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m+1;j++){
cin>>arr[i][j];
if(j>=2){
num[i]+=arr[i][j];
}
a1+=arr[i][j];
}
}
int flag=num[1];
int index=1;
for(int i=2;i<=n;i++){
if(num[i]<flag){
flag=num[i];
index=i;
}
}
cout<<a1<<" "<<index<<" "<<abs(flag);
return 0;
}
关键:
如果两棵树的疏果个数均为4,应该输出编号最小的第1棵树。
小中大(30分,重做)(类型转换int,double)
未仔细看题,漏了对于整数请直接输出整数,对于可能出现的分数请输出四舍五入保留1位小数的结果。
错误版
#include<iostream>
#include<algorithm>
using namespace std;
int flag;
int arr[100100]={0};
double ans;
int main(){
cin>>flag;
arr[0]=0;
for(int i=1;i<=flag;i++){
cin>>arr[i];
}
sort(arr+1,arr+flag);
cout<<arr[flag]<<" ";
if(flag%2==0){
int index=flag;
for(int j=1;j<=flag;j++){
if(index-j==1){
if((arr[index]+arr[j])%2!=0){
ans=(double)(arr[index]+arr[j])/2.0;
printf("%0.1lf ",ans);
}else {
ans=(int)(arr[index]+arr[j])/2;
printf("%d ",ans);
}
break;
}else index--;
}
}else if(flag%2!=0){
ans=arr[(flag+1)/2];
cout<<ans<<" ";
}
cout<<arr[1];
return 0;
}
满分版
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1e5;
int a[N];
int main()
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%d", &a[i]);
int mina = a[0], maxa = a[n - 1];
if(mina > maxa) swap(mina, maxa);
if(n % 2 == 1) {
printf("%d %d %d", maxa, a[n / 2], mina);
} else {
if((a[n / 2 - 1] + a[n / 2]) % 2 == 1)
printf("%d %.1lf %d", maxa, (double)((a[n / 2 - 1] + a[n / 2]) / 2.0), mina);
else
printf("%d %d %d", maxa, (a[n / 2 - 1] + a[n / 2]) / 2, mina);
}
return 0;
}
小明上学(简单秒杀)
//有0,1,2,3四种情况
//如果是0直接加
//如果是1直接加
//如果是3且t>0则加0,如果是3且t=0则加红灯
//如果是2则加当前的数再加红灯
//int r红灯,int y黄灯,int g绿灯
//int n几次循环
//int ans答案
#include<iostream>
using namespace std;
int r,y,g;
int n;
int ans=0;
int main(){
cin>>r>>y>>g;
cin>>n;
for(int i=1;i<=n;i++){
int k,t;
cin>>k>>t;
if(k==0||k==1){
ans+=t;
continue;
}
if(k==3&&t==0){
ans+=r;
continue;
}
if(k==2){
ans+=t+r;
continue;
}
}
cout<<ans;
return 0;
}
跳一跳(秒杀)
//三种情况
//遇到0时结束
//遇到1时相加并设flag=1
//遇到2时判断flag是否大于1,如果大于则加上flag并使flag+=2,如果不大于1则加上2并使flag=4
#include<iostream>
using namespace std;
int flag=1;
int ans=0;
int main(){
while(true){
int k;
cin>>k;
if(k==0)break;
if(k==1){
ans+=1;
flag=1;
}
if(k==2){
if(flag>1){
ans+=flag;
flag+=2;
}
if(flag==1){
ans+=2;
flag=4;
}
}
}
cout<<ans;
return 0;
}
最小差值 (秒杀)
//int index=n指针指向数组最后一个元素
//首先排序
//先算出当前的差值
//然后算出右边往前一个index-1的差值
//再算出左边往前i+1 的差值
//谁小谁实现
//如果两个一样默认右边往前一个
//三种情况
#include<iostream>
#include<algorithm>
using namespace std;
int index;
int n;
int arr[1010]={0};
int ans;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>arr[i];
}
index=n;
int flag=1;
sort(arr+1,arr+n+1);
while(true){
int judge=arr[index]-arr[flag];
int left=arr[index]-arr[flag+1];
int right=arr[index-1]-arr[flag];
if(index-flag==1){
ans=arr[index]-arr[flag];
break;
}
if(left<right){
flag++;
continue;
}else if(left>=right){
index--;
continue;
}
}
cout<<ans;
return 0;
}
打酱油(秒杀)
//三种情况
//N大于等于50则N-=50 ans+=7
//N大于等于30则N-=30 ans+=4
//N小于30则ans+=N/10
#include<iostream>
using namespace std;
int ans=0;
int N;
int main(){
cin>>N;
while(true){
if(N>=50){
N-=50;
ans+=7;
continue;
}
if(N>=30){
N-=30;
ans+=4;
continue;
}
if(N<30){
ans+=N/10;
break;
}
}
cout<<ans;
return 0;
}
分蛋糕(80分,理解题意不全面)
80分:认为蛋糕可分,其实蛋糕整分
//三种情况
//当前元素和小于k则continue,不够,要下一个
//当前元素和大于k则当前元素-=k,ans++,够了
//加上最后一个元素仍小于k,ans++ ,还有剩的
#include<iostream>
using namespace std;
int n,k;
int arr[1010]={0};
int ans=0;
int count=0;
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>arr[i];
}
for(int j=1;j<=n;j++){
count+=arr[j];
int flag=count-k;
if(flag>=0){
ans++;
count-=k;
}
if(j==n&&count!=0){
ans++;
}
}
cout<<ans;
return 0;
}
没有注意到样例说明:加到够了就分(ans++),类似背包问题的整拿整放,不能分开
满分:
//三种情况
//当前元素和小于k则continue,不够,要下一个
//当前元素和大于k则当前元素-=k,ans++,够了
//加上最后一个元素仍小于k,ans++ ,还有剩的
#include<iostream>
using namespace std;
int n,k;
int arr[1010]={0};
int ans=0;
int count=0;
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>arr[i];
}
for(int j=1;j<=n;j++){
count+=arr[j];
if(count>=k){
ans++;
count=0;
}
if(j==n&&count!=0){
ans++;
}
}
cout<<ans;
return 0;
}
中间数(90分,想复杂)
90分:
//序列中有相同元素(如5,6,6则大于5的有两个)
//排完序后最左右两边的数不可能是中间数
//不可能有两个中间数
//奇数个序列数(中间数一定是arr[(n+1)/2]) (三种情况)
//1、排完序后左小右大(下一个)
//2、排完序后左等右大(右加一)
//3、排完序后左小右等(左加一)
//最后判断左边等于右边输出中间数,否则输出-1
//偶数个序列数(中间数一定是arr[n/2]和arr[n/2+1]) (同上)
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int arr[1010]={0};
int ans=0;
int judge(){
int left=0;
int right=0;
int lmid=n/2;
int rmid=n/2+1;
int flag=rmid+1;
if(arr[lmid]!=arr[rmid])return -1;
for(int k=lmid-1;k>=1;k--){
if(arr[k]<arr[lmid]&&arr[flag]>arr[lmid]){
if(k==1&&left==right){
return arr[lmid];
}else if(k==1&&left!=right){
return -1;
}
flag++;
continue;
}
if(arr[k]==arr[lmid]&&arr[flag]>arr[lmid]){
right++;
}
if(arr[k]<arr[lmid]&&arr[flag]==arr[lmid]){
left++;
}
if(k==1&&left!=right){
return -1;
}else if(k==1&&left==right){
return arr[lmid];
}
flag++;
}
}
int Judge(){
int mid=(n+1)/2;//中间数
int left=0;
int right=0;
int flag=(n+1)/2+1;
for(int k=mid-1;k>=1;k--){
if(arr[k]<arr[mid]&&arr[flag]>arr[mid]){
if(k==1&&left==right){
return arr[mid];
}else if(k==1&&left!=right){
return -1;
}
flag++;
continue;
}
if(arr[k]==arr[mid]&&arr[flag]>arr[mid]){
right++;
}
if(arr[k]<arr[mid]&&arr[flag]==arr[mid]){
left++;
}
if(k==1&&left!=right){
return -1;
}else if(k==1&&left==right){
return arr[mid];
}
flag++;
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>arr[i];
}
sort(arr+1,arr+n+1);
if(n%2==0){//偶数
ans=judge();
}
if(n%2!=0){//奇数
ans=Judge();
}
cout<<ans;
return 0;
}
满分:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int sma_num = 0;
int big_num = 0;
int n;
cin>>n;
int num[n];
for(int i=0; i<n; i++)
cin>>num[i];
sort(num,num+n);
//奇数
if(n%2 != 0)
{
for(int i=0; i<n; i++)
{
if(num[i]<num[(n-1)/2])
sma_num++;
else if(num[i]>num[(n-1)/2])
big_num++;
}
if(sma_num == big_num)
cout<<num[(n-1)/2];
else
cout<<"-1";
}
//偶数
else
{
if(num[(n-1)/2] != num[n/2])
cout<<"-1";
else
{
for(int i=0; i<n; i++)
{
if(num[i]<num[(n-1)/2])
sma_num++;
else if(num[i]>num[(n-1)/2])
big_num++;
}
if(sma_num == big_num)
cout<<num[(n-1)/2];
else
cout<<"-1";
}
}
return 0;
}
最大波动(秒杀)
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int n;
int arr[1010]={0};
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>arr[i];
}
int max=0;
for(int j=2;j<=n;j++){
if(abs(arr[j]-arr[j-1])>max){
max=abs(arr[j]-arr[j-1]);
}
}
cout<<max;
return 0;
}
折点计数(秒杀)
#include<iostream>
using namespace std;
int n;
int arr[1010];
int ans=0;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>arr[i];
}
bool down=false;
bool up=false;
for(int j=2;j<n;j++){
if(arr[j]-arr[j-1]>0){
up=true;
down=false;
}else if(arr[j]-arr[j-1]<0){
up=false;
down=true;
}
if(arr[j+1]-arr[j]>0&&down==true){
ans++;
}else if(arr[j+1]-arr[j]<0&&up==true){
ans++;
}
}
cout<<ans;
}
数位之和(秒杀)
#include<iostream>
using namespace std;
long n;
long ans=0;
int main(){
cin>>n;
while(true){
if(n==0)break;
ans+=n%10;
n=n/10;
}
cout<<ans;
return 0;
}
数列分段(秒杀)
#include<iostream>
using namespace std;
int arr[1010]={0};
int n;
int ans=0;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>arr[i];
}
for(int j=1;j<=n;j++){
if(j==1){
ans++;
continue;
}
if(arr[j]!=arr[j-1]){
ans++;
}else{
continue;
}
}
cout<<ans;
return 0;
}
稍微考虑一下左右两边边界问题(第一个数时和最后一个数时的情况)
图像旋转(矩阵转置,秒杀)
#include<iostream>
using namespace std;
int n,m;
int arr[1010][1010]={0};
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>arr[i][j];
}
}
for(int i=m;m>=1;m--){
for(int j=1;j<=n;j++){
cout<<arr[j][m]<<" ";
if(j==n){
cout<<endl;
}
}
}
return 0;
}
门禁系统(秒杀)
#include<iostream>
using namespace std;
int n;
int arr[1010]={0};
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int flag;
cin>>flag;
arr[flag]++;
cout<<arr[flag]<<" ";
}
return 0;
}
相邻数对(秒杀)
//1个数就输出0
//差1则ans++
//遍历由1到n-1
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int arr[1010]={0};
int ans=0;
int main(){
cin>>n;
if(n==1){
return 0;
}
for(int i=1;i<=n;i++){
cin>>arr[i];
}
sort(arr+1,arr+n+1);
for(int i=1;i<=n-1;i++){
if(arr[i+1]-arr[i]==1){
ans++;
}
}
cout<<ans;
return 0;
}
相反数(秒杀)(考虑最后一次循环的情况)(循环控制结束语句应放在循环体前面)(continue语句有时会使循环无法结束)
//相加等于0则ans++,left+1,right-1
//相加大于0则右边-1
//相加小于0则左边+1
//如果right=left或者right-left=1则break
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int arr[1000]={0};
int ans=0;
int main(){
cin>>n;
if(n==1)return 0;
int left=1;
int right=n;
for(int i=1;i<=n;i++){
cin>>arr[i];
}
sort(arr+1,arr+n+1);
while(true){
if(right-left==1 || right==left){
if(arr[left]+arr[right]==0){
ans++;
}
break;
}
if(arr[left]+arr[right]==0){
ans++;
left++;
right--;
continue;
}
if(arr[left]+arr[right]>0){
right--;
continue;
}
if(arr[left]+arr[right]<0){
left++;
continue;
}
}
cout<<ans;
return 0;
}
出现次数最多的数(key-value形式)(可重做)
使用二维数组表示键值对
#include <stdio.h>
//num[i][0]存储列表中出现的数,num[i][1]记录该数在当前列表中出现的次数
static int num[1001][2]={0};
int main()
{
int i,j;
int n,number;
int max; //max记录当前列表中出现次数最多的数的出现次数
int min; //min记录当前列表中出现次数最多的数中的最小的数
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&number);
for(j=0;num[j][0]!=0;j++)
{
if(num[j][0]==number) break; //若当前列表中有该元素,跳出循环
}
if(num[j][0]==0) num[j][0]=number; //若当前列表中没有该元素,添加该元素到列表尾部
num[j][1]++; //当前元素出现的次数加一
if(i==0) max=num[0][1],min=num[0][0]; //i等于0时,初始化max和min
else
{
//若当前元素的出现次数比上一次记录的出现次数最多的数多,更新max和min
if(num[j][1]>max) max=num[j][1],min=num[j][0];
//若当前元素的出现次数等于上一次记录的出现次数最多的数,并且该数比上一次记录的出现次数最多的数小,更新min
else if(num[j][1]==max&&num[j][0]<min) min=num[j][0];
}
}
printf("%d\n",min);
return 0;
}
满分:
#include<iostream>
using namespace std;
int arr[10010][2]={0};
int n;
int flag;
int ans=0;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>flag;
arr[flag][0]=flag;
arr[flag][1]++;
}
int max=-1;
for(int i=1;i<=10010;i++){
if(arr[i][1]>max){
max=arr[i][1];
ans=i;
}
}
cout<<ans;
return 0;
}
出现运行错误
原因:答案的范围为1到10000,但是数组和循环只开到了1000,错把一共有几个数当成答案范围
解决:检查数组是否越界,循环是否出错
第二题
ISBN号码
第一遍(50分)
#include<iostream>
using namespace std;
int sum;
int ans[10];
int flag=1;
char s[14];
int main(){
for(int i=1;i<=13;i++){
cin>>s[i];
if(s[i]=='-'){
continue;
}else{
ans[flag]=(int)(s[i]);
sum+=flag*ans[flag];
flag++;
}
}
sum=sum%11;
int index=(int)(s[13]);
if(sum==index){
cout<<"Right";
}else{
for(int i=1;i<=13;i++){
cout<<s[i];
}
}
return 0;
}
窗口
第一版
//没点到输出IGNORED
//点到了一个窗口则输出其序号并将其置顶
//点到了多个窗口则判断谁在上,在上的输出其序号并置顶
//x1,y1,x2,y2数组
//int index序号大的在上
//int N个窗口
//int M次点击
#include<iostream>
using namespace std;
int x1[100],x2[100],y1[100],y2[100];
int index[100];//序号
int N,M;
int main(){
cin>>N>>M;
for(int i=1;i<=N;i++){
cin>>x1[i]>>y1[i]>>x2[i]>>y2[i];
index[i]=i;
}
for(int i=1;i<=M;i++){
int x,y;
cin>>x>>y;
for(int j=N;j>=1;j--){
if(x>=x1[j]&&x<=x2[j]&&y>=y1[j]&&y<=y2[j]){
//输出序号,放到前面
cout<<index[j];
}
if(j==1){
cout<<"IGNORED"<<endl;
break;
}
}
}
return 0;
}
画图
没思路
解决:求每个不同的方格有几个
#include <iostream>
#include <map>
#include <string>
#include <sstream>
using namespace std;
// 将整数转换为字符串的函数
string itos(int n){
stringstream tem; // 创建一个字符串流对象
tem << n; // 将整数n插入到字符串流中
return tem.str(); // 返回字符串流中的字符串表示
}
int main(){
int num; // 存储输入的点的数量
int point[4]; // 用于存储一个矩形的两个对角线点的坐标
map<string,int> area; // 使用map来存储每个方格出现的次数
cin >> num; // 输入点的数量
for(int i = 0; i < num; i++){
cin >> point[0] >> point[1] >> point[2] >> point[3]; // 输入矩形的两个对角线点的坐标
// 给的是点,求得是方格
for(int m = point[0] + 1; m <= point[2]; m++){ // 遍历矩形的x坐标
for(int n = point[1] + 1; n <= point[3]; n++){ // 遍历矩形的y坐标
string key = itos(m) + "-" + itos(n); // 创建方格的唯一标识符,格式为"x-y"
++area[key]; // 方格出现次数加1
}
}
}
cout << area.size(); // 输出不同方格的总数
return 0;
}
Z字形扫描
//设置flag=true时,x--,y++
//设置flag=false时,x++,y--
//判断如果下一个结点越界则根据flag选择
//true时y++,false时,x++ 且变换flag
//如果结点为(n,n)则输出并退出
#include<iostream>
using namespace std;
bool flag=true;
int arr[510][510]={0};
int x=1;
int y=1;
int n;
bool judge(){
if(flag==true&&x-1==0){
flag=false;
y++;
return false;
}else if(flag==false&&y-1==0){
x++;
flag=true;
return false;
}else return true;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>arr[i][j];
}
}
while(true){
if(x==n||y==n){
break;
}
cout<<arr[x][y]<<" ";
if(judge()){
if(flag==true){
x--;
y++;
continue;
}else if(flag==false){
x++;
y--;
continue;
}
}else continue;
}
cout<<arr[n][n];
return 0;
}