洛谷题单难题总结——数组

第一题:旗鼓相当的对手

题目描述

有N个同学,每个同学三科成绩(每门分数<=150),如果两名同学<i,j>的总分不超过10分且单科分差不超过5分,则两个同学是旗鼓相当的对手,求总对数。

样例测试

74a3dffeced203148d147b5da7f8362d.png

AC代码


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

int main(){
    int N;        //参加的同学人数 
    cin>>N;
    int a[N][3];
    int sum=0;        //旗鼓相当的对手个数 
    int sum1,sum2;        //两个同学各自的总分 
    for(int i=0;i<N;i++){        //录入成绩 
        cin>>a[i][0]>>a[i][1]>>a[i][2];
    }
    
    for(int i=0;i<N-1;i++){
        sum1 = a[i][0]+a[i][1]+a[i][2];
        for(int j=i+1;j<N;j++){
            sum2 = a[j][0]+a[j][1]+a[j][2];
            if(abs(sum1-sum2)>10){    //判断总成绩分差
                continue;
            }else{                     //判断单科分差
                if(abs(a[i][0]-a[j][0])<=5 && abs(a[i][1]-a[j][1])<=5 && abs(a[i][2]-a[j][2])<=5){
                    sum++; 
                }    
            }
        }
    }
    
    cout<<sum;        //输出总个数 
    return 0;
}    

易错点

计算分差带绝对值abs()

切记数组下标从0开始


第二题:工艺品制作

题目描述

有一个长宽高分别为w,x,h的实心玻璃立方体,由1*1*1的方块组成,每个方块坐标(i,j,k)。现对该方块进行q次切割,切割出立方体空洞,每次切割的对角坐标为(x1,y1,z1)和(x2,y2,z2)且保证1<=w<=20,1<=q<=100,1<=x1<=x2<=w,1<=y1<=y2<=x,1<=z1<=z2<=h。求切割完成后剩余的小方块个数sum。

样例测试

0ce923ee62f6c3260011d48497168e03.png

AC代码


#include<bits/stdc++.h>
using namespace std;
int a[21][21][21];    //定义在函数外部的数组默认赋0 

int main(){
    int sum=0;    //剩余方块个数 
    int w,x,h;    //长,宽,高 
    int q;        //切割次数 
    int x1,y1,z1,x2,y2,z2;    //两个切割点 
    
    cin>>w>>x>>h;
    cin>>q;
    
    while(q--){
        cin>>x1>>y1>>z1>>x2>>y2>>z2;
        for(int i=x1;i<=x2;i++){
            for(int j=y1;j<=y2;j++){
                for(int k=z1;k<=z2;k++){
                    a[i][j][k] = 1;
                }
            }
        }
    }
    
    for(int i=1;i<=w;i++){
        for(int j=1;j<=x;j++){
            for(int k=1;k<=h;k++){
                if(a[i][j][k] == 0){
                    sum++;
                }
            }
        }
    }
    
    cout<<sum;
    return 0; 
}    

易错点

整型数组定义在main函数外部时,默认值为0


第三题:彩票摇奖

题目描述

现有一项彩票活动,规则如下:

  1. 每张彩票上印有 7 个各不相同的号码,且这些号码的取值范围为1~33

  1. 每次在兑奖前都会公布一个由7个各不相同的号码构成的中奖号码

  1. 设置特等奖和一到六等奖共7个奖项,对应猜中号码个数7~1,不考虑号码位置

依次输入小明购买的彩票个数、中奖号码以及小明购买的所有彩票号码,统计其各个奖项的中奖次数,从特等到六等排序。

样例测试

8dd339dd9cdea7743e361a59ac12623d.png

AC代码


#include<bits/stdc++.h>
using namespace std;
int price[7];    

int main(){
    int num,s;    //彩票张数,相同号码个数 
    int a[7];    //中奖号码串
    int temp;    //每次输入购买号码 
    
    cin>>num;    //输入数据 
    for(int i=0;i<7;i++){
        cin>>a[i];
    }
    
    while(num--){
        s = 0;    //初始化相同个数为0 
        for(int i=0;i<7;i++){
            cin>>temp;
            for(int i=0;i<7;i++){
                if(temp==a[i]){
                    s++;
                    break;
                }
            }
        }
        if(s>0){
            price[7-s]++;    //对应奖项(特等~六等) 
        }
    }
    
    for(int i=0;i<7;i++){   //输出结果 
        cout<<price[i]<<' '; 
    }
    
    return 0; 
}    

第四题:神奇的幻方

题目描述

幻方是一种很神奇的N*N 矩阵:它由数字1,2,3,⋯⋯,N*N 构成,且每行、每列及两条对角线上的数字之和都相同,构建方法如下:

17f6fa17f053177fe0896642ce793f51.png

现给定N,请按照上述方法构造N*N幻方。

样例测试

876b29d316742fa6d7db2a017c0ab83e.png

AC代码


#include<bits/stdc++.h>
using namespace std;
int price[7];    

int main(){
    int N;        //幻方的边长(奇数)
    cin>>N;
    int num=N*N;        
    int K=1;     //初始值
        
    int a[N][N];    //定义幻方矩阵 
    memset(a,0,sizeof(a));    //初始化为0 
    a[0][N/2] = 1;         //第一行中间为 1 
    
    int row,column;        //上一个幻方的行、列
    row = 0;
    column = N/2; 
    while(K<num){
        K++;
        if(row==0 && column!=N-1){    //1、第一行但不是最后一列 
            row = N-1;
            column++;
            a[row][column] = K;
            continue;
        }
        if(row!=0 && column==N-1){    //2、第一列但不是最后一行 
            row--;
            column = 0;
            a[row][column] = K;
            continue;
        }
        if(row==0 && column==N-1){    //3、右上角 
            row++;
            a[row][column] = K;
            continue;
        }
        if(row!=0 && column!=N-1){    //4、不是第一行也不是最后一列 
            if(a[row-1][column+1]==0){
                row--;
                column++;
                a[row][column] = K;
                continue;        
            }else{
                row++;
                a[row][column] = K;
                continue;
            }
        }
    }
    
    for(int i=0;i<N;i++){        //输出幻方
        for(int j=0;j<N;j++){
            cout<<a[i][j]<<' ';
        }
        cout<<endl;
    }
     
    return 0;
}    

易错点

定义静态数组时要用常量,若用不确定的变量N初始化数组长度,则可以用memset初始化数组的值。


第五题:珠心算测验

题目描述

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

样例测试

438056263c0d3000ca55aa7c74af54c2.png

AC代码


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

int main(){
    int num,tag;      //数字总数,该数字是否已进入数组 
    int sum=0;        //两数之和符合条件的对数 
    cin>>num;        
    int a[num];        //创建数组存储数字 
    for(int i=0;i<num;i++){
        cin>>a[i];
    }
    
    sort(a,a+num);    //排序后不用枚举比自己大的数,降低时间复杂度
    
    for(int i=2;i<num;i++){        //枚举第3位和以后的数 
        tag = 1;    //刷新数字状态 
        for(int j=0;j<i-1;j++){        //首位数字到枚举数字的前两位为止 
            for(int k=j+1;k<i;k++){    //次位数字到枚举数字的前一位为止 
                if(tag && a[j]+a[k]==a[i]){
                    sum++;
                    tag = 0;
                }
            }
        }
    } 
    cout<<sum; 
    return 0;
}

易错点

本题要寻找的是符合条件的数字的个数,而不是符合条件的算式个数,所以要使用一个标记tag,当某个数字第一次符合要求时总数+1,后续若该数字仍满足则总数不加。


第六题:爱与愁的心痛

题目描述

最近有n个不爽的事,每件事都有一个正整数刺痛值(心理承受力极差)。爱与愁大神想知道连续m个刺痛值的和的最小值是多少,但是由于业务繁忙,爱与愁大神只好请你编个程序告诉他。

样例测试

8e6408aa68a79934ddae6f5a7fb189ec.png

 

AC代码


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

int main(){
    int n,m;        //n件事;求连续m件事的最小刺痛值 
    int temp,sum;    //临时最小值;每次连续m刺痛值的和 
    cin>>n>>m;
    int a[n];
    
    for(int i=0;i<n;i++){    //存储到数组 
        cin>>a[i];
    }
    
    for(int i=0;i<=n-m;i++){
        sum = 0;
        for(int j=i;j<i+m;j++){
            sum += a[j];
        }
        if(i==0){            //第一次计算sum值直接赋值给temp 
            temp = sum;
        }else{                //后续赋最小值 
            temp = min(temp,sum); 
        }
    } 
    
    cout<<temp;
    return 0;
}

易错点

确定m宽的滑窗初始地址时,要保证能取到a[n-m],即i<=n-m。


第七题:插火把

题目描述

在游戏《我的世界》里选定n*n的空地,分别放置火把和萤石,可以照亮周围的一些区域,范围如下:


火把:|暗|暗| 光 |暗|暗|   萤石:|光|光| 光 |光|光|
     |暗|光| 光 |光|暗|        |光|光| 光 |光|光|
     |光|光|火把|光|光|        |光|光|萤石|光|光|
     |暗|光| 光 |光|暗|        |光|光| 光 |光|光|
     |暗|暗| 光 |暗|暗|        |光|光| 光 |光|光|

分别输入n(边长),m(火把数),k(萤石数)

第2~m+1行输入火把坐标,继而输入萤石坐标

最后输入可以生成怪物的格子数

样例测试

86113eb01cd197db0d3caf66ec106436.png

AC代码


#include<bits/stdc++.h>
using namespace std;
int T[110][110];    //最大的面积 
 
int main(){
    int n,m,k;        //列数,火把数,萤石数 
    int x,y;        //火把 萤石的坐标 
    int sum=0;        //可以生成怪物的格子总数 
    cin>>n>>m>>k;
    
    for(int i=1;i<=m;i++){    //火把照亮 
        cin>>x>>y;
        x += 2;                //防止越界产生RE 
        y += 2; 
        for(int j=-2;j<=2;j++){
            T[x+j][y] = 1;
            T[x][y+j] = 1;
        }
        T[x-1][y-1]=T[x+1][y-1] = 1;    //补充四个角 
        T[x-1][y+1]=T[x+1][y+1] = 1;
    }

    for(int i=1;i<=k;i++){    //萤石照亮 
        cin>>x>>y;
        x += 2;
        y += 2;
        for(int j=0;j<=2;j++){
            for(int h=0;h<=2;h++){
                T[x+j][y+h] = 1;
                T[x+j][y-h]    = 1;
                T[x-j][y+h] = 1;
                T[x-j][y-h] = 1;        
            }
        }
    } 
    
    for(int i=3;i<=n+2;i++){
        for(int j=3;j<=n+2;j++){
            if(T[i][j]==0){
                sum++;
            }
        }
    }
    
    cout<<sum;
    return 0;
}

易错点

对数组越界部分赋值会造成超时RE

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

掇星攫辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值