nyist 2022/9/29结构体专场题解~

本文详细介绍了结构体在编程中的应用,包括规范字符串输出、查找特定数据、按特定规则排序等。通过实例解析了如何使用结构体存储数据、处理查询以及实现排序算法,涉及的技巧包括结构体定义、数据输入、排序函数cmp的编写等。文章还讲解了如何处理数据结构和算法题目中的难点,如处理不同条件下的排序和判断。
摘要由CSDN通过智能技术生成


本场专题主要考察结构体和对sort的运用,请各位学弟学妹熟练运用并加油补题噢~

本场难度并不呈递增趋势,于是lk按照自己的想法将题目的难度自己规划了一下,简单的在前,难的在后,想看哪一题的可以自己去跳转噢~

注: 题解都是由lk独自一人完成,所以难免会有所瑕疵,还往各位学弟学妹多多谅解,然后有什么意见和问题都可以在群里说出来噢~、

2)结构体都是LK的!(怎么会是lk的呢!)

这题我愿意称之为最水!!!

其实就是非常简单,输入一个字符串然后规范输出格式就好啦~

#include<stdio.h>
#include <iostream>
using namespace std;

char cnt[1000];

int main()
{
    scanf("%s",cnt);
    printf("struct %s{};",cnt);
  

	return 0;
}

最后记得数组空间要开大些噢!

4)lk的关怀

​​

题目简单的描述一下:

给你n个ikui的名字以及他们手中拿到的数字,然后给你q次询问,每次输入一个数,问你有没有ikui手中拿到的数字和这个数相同,如果有就输出这个ikui的名字,如果没有就输入“不存在此 ikui”。

思路:
首先结构体的建立:

struct lk{
    char str[11];
    int num;
}cnt[110];

之后是输入数据

        for(int i =1;i<=n;i++)
        cin>>cnt[i].str>>cnt[i].num;

然后q次询问,每次询问判断一下,如果相同就输出。这里我们定义了一个pan变量,用来判断有没有相同的数,如果pan=0说明没有相同的数就可以直接输出没有这个ikui

        for(int i =1;i<=m;i++)
        {
            int query;
            cin>>query;
            int pan=0;
            for(int j =1;j<=n;j++)
            {
                if(cnt[j].num==query)//如果相同就输出
                {
                    cout<<cnt[j].str<<endl;
                    pan=1;//标记有输出的
                }
            }
            if(!pan)//说明没有这个数
            cout<<"不存在此 ikui"<<endl;            
        }

##最后代码

#include<stdio.h>
#include <iostream>
#include <algorithm>
#define ll long long 
using namespace std;

struct lk{
    char str[11];
    int num;
}cnt[110];

int main()
{
	int t,n,m;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(int i =1;i<=n;i++)
        cin>>cnt[i].str>>cnt[i].num;

        for(int i =1;i<=m;i++)
        {
            int query;
            cin>>query;
            int pan=0;
            for(int j =1;j<=n;j++)
            {
                if(cnt[j].num==query)//如果相同就输出
                {
                    cout<<cnt[j].str<<endl;
                    pan=1;//标记有输出的
                }
            }
            if(!pan)//说明没有这个数
            cout<<"不存在此 ikui"<<endl;            
        }
    }

	return 0;
}

5)CK教练有点忙

这道题属于水题之外的一个比较好的一个练习题,只需要掌握好sort排序和结构体的输入就可以轻松完成!

题意:告诉你每个人的名字,数学,英语,语文成绩然后让你输出总成绩最高的人的名字,如果总成绩相同就输出数学成绩高的。

重点就是cmp的写法啦
如果总成绩不相同就返回总成绩大的,如果总成绩最大且相同就返回数学成绩最大的

bool  cmp(lk x , lk y )
{
    if(x.sum!=y.sum)return x.sum>y.sum;//按总成绩排序
    else return x.Math>y.Math;//如果总成绩相同按数学成绩排序
}

注意数据范围是1e6记得开大点!!!

代码:

#include<stdio.h>
#include <iostream>
#include <algorithm>
#define ll long long 
using namespace std;

struct lk{
 char name[100];
 int Chinese;
 int Math;
 int English;
 int sum;
}cnt[1100000];

bool  cmp(lk x , lk y )
{
    if(x.sum!=y.sum)return x.sum>y.sum;//按总成绩排序
    else return x.Math>y.Math;//如果总成绩相同按数学成绩排序
}

int main()
{
	int n;
    cin>>n;
    for(int i =0;i<n;i++){
    cin>>cnt[i].name>>cnt[i].Chinese>>cnt[i].Math>>cnt[i].English;
    cnt[i].sum=cnt[i].Math+cnt[i].Chinese+cnt[i].English;
    }
    
    sort(cnt,cnt+1+n,cmp);
    cout<<cnt[0].name;
	return 0;
}

7) 合影效果

题意:

给你n个人,每个人都有自己的身高,其中包含男生跟女生,然后让你按男生从小到大,女生从大到小的排序方法排序并输出(要求先输出男生的所有人再输出女生的所有人)

思路:首先可以建立两个结构体数组分别代表男生和女生,之后分开写两个cmp函数进行排序就可以啦~

代码:

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
struct lk
{
   	double high;
}man[44],girl[44];

bool cmp(lk x , lk y ){
    return x.high>y.high; 
}

bool cmp1(lk x ,lk y ){
    return x.high<y.high;
}

int main()
{
   int n;
   cin>>n;
   int man_pe=0,girl_pe=0;//用man_pe,girl_pe代表有男生/女生人数的个数
    while(n--)
    {

        char str[10];
        double x;
        cin>>str>>x;
        if(str[0]=='m')
        man[man_pe++].high=x;
        else 
        girl[girl_pe++].high=x;
    }
        sort(man,man+man_pe,cmp1);
        sort(girl,girl+girl_pe,cmp);
        for(int i =0;i<man_pe;i++)
        printf("%.2lf ",man[i].high);
        for(int i =0;i<girl_pe;i++)
        printf("%.2lf ",girl[i].high);

    return 0;
}

3)嘉门

lk:嘉门!!!!(超大声)

题意:

细读题目,发现我们的结构体需要四个属性:人名,小作文的分数,参加佳然的活动的次数和总得分。

那么我们定义一个嘉然!(大声)的结构体

struct JiaRan{
    char name[1000];//人名,因为不知道长度有多少所以开大些啦~
    double grade;//作文分数
    double add;//参加活动次数
    double sum;//总分!
}cnt[1100000];//注意题目数据范围!

因为题目的样例给了小数点所以用double来接受数据啦(后台数据到底有没有小数点我也不知555 qwq~)

然后sum可以在我们输入数据的时候时直接计算出来啦~又快又方便的呢

  cin>>n;
    for(int i =0;i<n;i++){
    cin>>cnt[i].name>>cnt[i].grade>>cnt[i].add;
    cnt[i].sum=cnt[i].add+cnt[i].grade;
    }

然后这就需要我们用到另一个关键的知识点了:sort!

sort和结构体形成奇妙的化学反应:结构体排序!

那么我们应该怎么排序呢?

​​​​

好,现在知道道长想知道喜欢嘉然中总得分最高的,

那么如果总得分不相同时我们应该按照总得分从小到大排序,

但是他下面还有一个条件是什么呢,

如果总得分相同则输出活动书最多的,那么我们就可以在总得分相同时按活动数从大到小排序

于是排序方法如下图:

bool cmp(JiaRan x, JiaRan y )
{
    if(x.sum!=y.sum)return x.sum>y.sum;//如果总成绩不相同就按总成绩从大到小排序
    else return x.add>y.add;//否则按分数从大到小排序
}

好!现在我们数据输入完了,排序也排完了,

那么我们结构体中的数据就是我们想要的排序的顺序(问我哪样?自己往上翻!)

之后题目的要求是什么,是输出两个人名是

除了道长以外的 最 爱嘉然的道友和
最坏的小黑粉

那么我们先输出最 爱嘉然的道友

首先看要是爱嘉然的那么他的grade作文分必须大于60,并且参加活动的次数必须大于20.

那么我们可以从第一个开始判断(第一个是总分最大的啦),如果第i个人的grade>=60&&add>=20,那么他是爱嘉然的而且也是目前序列中最大的(因为前面的不满足条件)

所以我们就可以直接输出这个人名,然后跳出循环。

好,最 爱嘉然的道友我们输出完了我们就可以输出最坏的小黑粉了,

因为最坏的小黑粉是总成绩最小的,所以我们的循环要从n-1开始到0(从成绩最小的开始排序)

每次进行一个判断如果第i个人的小作文分小于60或者活动次数小于20(就是个小黑粉!)

那么我们就可以直接输出这个人的名字,然后跳出循环。

最后代码:

#include<cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int n ,m,h;


struct JiaRan{
    char name[1000];//人名,因为不知道长度有多少所以开大些啦~
    double grade;//作文分数
    double add;//参加活动次数
    double sum;//总分!
}cnt[1100000];//注意题目数据范围!


bool cmp(JiaRan x, JiaRan y )
{
    if(x.sum!=y.sum)return x.sum>y.sum;//如果总成绩不相同就按总成绩从大到小排序
    else return x.add>y.add;//否则按分数从大到小排序
}

int main()
{   
    cin>>n;
    for(int i =0;i<n;i++){
    cin>>cnt[i].name>>cnt[i].grade>>cnt[i].add;
    cnt[i].sum=cnt[i].add+cnt[i].grade;
    }

    sort(cnt,cnt+n,cmp);

    for(int i =0;i<n;i++)
    {
        if(cnt[i].add>=20&&cnt[i].grade>=60){
            cout<<"嘉然第二号粉丝 : "<<cnt[i].name<<endl;
            break;
        }
    }
    for(int i =n-1;i>=0;i--)
    {
        if(cnt[i].add<20||cnt[i].grade<60){
            cout<<"嘉然最坏小黑粉 : "<<cnt[i].name<<endl;
            break;
        }
    }

	return 0;
}

最后注意!!!!!!

题目中n的范围是1~1e6,所以我们一定要开相应的数组来防止错误!

7)线下丹砂

题意:

有两个人LJD和LK,每个人自身有3个属性
:血量,护甲和头盔。护甲可以抵挡来自四肢和
当每个人收到伤害时,当存在对应的护甲时,会消耗对应护甲的耐久(注:如果当此护甲耐久小于这次伤害时护甲会直接损害但是不会伤害到自己)
然后是n次枪战,每一次输入LJD或者LK和打击的部位,问你谁胜利(血量大于0)

挺麻烦的一道题,主要是写起来有点麻烦还有细节问题需要处理:比如大小写,比如护甲的值小于伤害值并不会造成人物的血量丢失…当然,慢慢来,一步一步走,就还是能写好的!

这里我用一个pan用来判断是谁的血量小于等于0,如果是lk血量小于等于0就pan为1,
否则pan为-1.

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
struct lkk
{
 int blood;//血
 int head;//身体护甲
 int body;//头护甲
}lk,ljd;



int main()
{
    cin>>lk.blood>>lk.body>>lk.head;
    cin>>ljd.blood>>ljd.body>>ljd.head;
    int n;
    cin>>n;
    int pan=0;
    while(n--)
    {
        char a[10],b[10];
        cin>>a>>b;
        if(a[1]=='K')//说明受伤的是lk学长
        {
            if(b[0]=='b'){//打击部位是腿
            if(lk.body==0)//没有护甲了;
            lk.blood-=10;
            else {//还有护甲
                    if(lk.body-10<=0)lk.body=0;//护甲消失
                    else lk.body-=10;
                }
            }
            else if(b[0]=='l'){//打击部位为背部
            if(lk.body==0)//没有护甲了;
            lk.blood-=30;
            else {//还有护甲
                    if(lk.body-30<=0)lk.body=0;//护甲消失
                    else lk.body-=30;
                }
            }            
            else{
            if(lk.head==0)//没有护甲了;
            lk.blood-=100;
            else {//还有护甲
                    if(lk.head-100<=0)lk.head=0;//护甲消失
                    else lk.head-=100;
                }
            }
            if(lk.blood<=0)pan=1;
        }
        else{
            if(b[0]=='b'){//打击部位是腿
            if(ljd.body==0)//没有护甲了;
            ljd.blood-=10;
            else {//还有护甲
                    if(ljd.body-10<=0)ljd.body=0;//护甲消失
                    else ljd.body-=10;
                }
            }
            else if(b[0]=='l'){//打击部位为背部
            if(ljd.body==0)//没有护甲了;
            ljd.blood-=30;
            else {//还有护甲
                    if(ljd.body-30<=0)ljd.body=0;//护甲消失
                    else ljd.body-=30;
                }
            }            
            else{
            if(ljd.head==0)//没有护甲了;
            ljd.blood-=100;
            else {//还有护甲
                    if(ljd.head-100<=0)ljd.head=0;//护甲消失
                    else ljd.head-=100;
                }
            }
            if(ljd.blood<=0)pan=-1;
            // cout<<ljd.blood<<" "<<ljd.body<<" "<<ljd.head<<endl;
        }
    }
    if(pan==1)cout<<"LJD";
    else cout<<"LK";
    return 0;
}

1)学长请客 !!

学长请客 !! - NYOJ

这一题体面比较长并且有点杂,如果是初学者这道题适合往后做。

题意简单的说明一下:

有n个学弟,每个学弟有自己喜欢的菜,一开始桌上什么菜都没有,然后给你k次上菜的机会,从0到n-1 位开始上,如果k>n的话,就从第0个重新上。然后上菜机会轮到第i为同学时,如果桌上有这位同学喜欢的菜,那么这位同学就会吃这一道菜并且自己的幸福度++,否则他会上这道菜并且上菜机会轮到下一个同学。让你求出所有同学的幸福度。

有很多同学不知道为什么要用i%n来代表轮到了哪位同学,那么我在这里着重讲一下:
因为我们的同学是从0-n-1存储的,那么我们的上菜(吃菜)机会肯定是要从0-n-1这些同学轮流的,此时我们看i%n这个操作,因为i%n的值我们知道只可能为0,1,2,3,…n-1刚好可以和我们同学的编号形成对应关系,i%n最大的数是n-1往后挪一位就是0也就是第一位同学符合我们的环形轮流上菜吃菜(要求)。

这道题看起来比较复杂,我们可以逐步模拟一下。首先是学弟的喜欢的菜和学弟的幸福度可以定义一个结构体来存储

struct lk{
    int sum;//幸福度之和
    int like;//喜欢的菜
}cnt[1010];

之后我们需要判断我们的菜是否存在,这时我们可以定义一个菜数组

int caicai[1010];//菜是否存在

因为caicai数组的默认值为0,我们可以定义caicai数组为0时菜不存在,为1时存在这个菜。

好。现在我们的大致框架就写好啦,先输入每一个学弟喜欢的菜,然后k次循环判断一下每位学弟想吃的菜存不存在,如果不存在学弟就会上这个菜

if(caicai[cai]==0)caicai[cai]=1;

如果存在学弟就会吃掉这个菜,并且幸福度++,

 cnt[t].sum++;
caicai[cai]=0;

然后就直接输出学弟们的幸福度就好啦!

细节:首先for怎么写,因为k是可能大于n的,所以我们可以存储数组时从0存到n-1的位置,那么用i%k每次都可以得到有上菜机会的学弟(i<n时i%n为i,如果i>n时i%n就是要上菜的学弟啦,可以自己试一试~)。

最后!!注意caicai数组和sum数组的初始化!

最后代码:

#include<stdio.h>
#include <iostream>
using namespace std;


struct lk{
    int sum;//幸福度之和
    int like;//喜欢的菜
}cnt[1100];

int caicai[1100];//菜是否存在

int main()
{
	int t ;
    cin>>t;
    while(t--)
    {
        int n,k;
        cin>>n>>k;
        for(int i =0;i<n;i++){
        cin>>cnt[i].like;
        caicai[cnt[i].like]=0;//这一道菜赋值为0代表桌上没有菜
        cnt[i].sum=0;//每位同学的幸福值赋值为0
        }
        
        for(int i =0;i<k;i++)//记着从0到n-1开始循环噢
        {
            int t=i%n,cai=cnt[t].like;//t表示第t为同学的上菜机会,cai表示为这为同学喜欢吃的菜
            if(caicai[cai]==0)caicai[cai]=1;
            else {
                cnt[t].sum++;
                caicai[cai]=0;
            }
        }
        for(int i =0;i<n;i++)
        cout<<cnt[i].sum<<" ";
        cout<<endl; 
    }

	return 0;
}

最后注意!!!

lk幸幸苦苦写了这么久的题解在这里插入图片描述
还麻烦给lk一个赞好不好嘛,这对lk真的不重要QAQ!!!

以下是51单片机控制的12864液晶显示系统编程实现所需的代码: ``` #include <reg51.h> #include <intrins.h> #define LCD_DB P0 sbit LCD_RS = P2^6; // RS信号 sbit LCD_RW = P2^5; // RW信号 sbit LCD_E = P2^7; // E信号 sbit LCD_CS1 = P2^0; // CS1信号 sbit LCD_CS2 = P2^1; // CS2信号 void delay(unsigned int i) // 延时函数 { while(i--); } void write_com(unsigned char com) // 写命令函数 { LCD_RS = 0; LCD_RW = 0; LCD_DB = com; LCD_E = 1; _nop_(); _nop_(); LCD_E = 0; } void write_data(unsigned char dat) // 写数据函数 { LCD_RS = 1; LCD_RW = 0; LCD_DB = dat; LCD_E = 1; _nop_(); _nop_(); LCD_E = 0; } void init_lcd() // 初始化函数 { write_com(0xc0); // 设置显示模式 write_com(0x3f); // 允许显示 write_com(0x40); // 设置起始地址 write_com(0xb8); // 设置页地址 write_com(0xc0); // 设置列地址 write_com(0x40); // 设置起始地址 write_com(0xb8); // 设置页地址 write_com(0xc0); // 设置列地址 } void display_string(unsigned char x, unsigned char y, unsigned char *s) // 显示字符串函数 { unsigned char i; if(y == 0) // 第一行居中显示“南阳理工学院” { write_com(0xb8 + x); write_com(0x40); } else if(y == 1) // 第二行居中显示“www.nyist.edu.cn” { write_com(0xb8 + x); write_com(0x48); } else if(y == 2) // 第三行居中显示“电子信息工程专业” { write_com(0xb8 + x); write_com(0x50); } else if(y == 3) // 第四行居中显示尚春芳 { write_com(0xb8 + x); write_com(0x58); } for(i = 0; s[i] != '\0'; i++) { write_data(s[i]); } } void main() { init_lcd(); // 初始化LCD display_string(18, 0, "南阳理工学院"); // 显示第一行 display_string(16, 1, "www.nyist.edu.cn"); // 显示第二行 display_string(16, 2, "电子信息工程专业"); // 显示第三行 display_string(22, 3, "尚春芳"); // 显示第四行 while(1); } ``` 以上代码实现了你提出的要求,第一行居中显示“南阳理工学院”,第二行居中显示“www.nyist.edu.cn”,第三行居中显示“电子信息工程专业”,第四行居中显示尚春芳。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值