“真采杯” G题:碧蓝航线 (qsort + 结构体 + 多级排序)

G题:碧蓝航线[题解]

  • (一)题目
    • 输入
    • 输出
    • 样例
  • (二)题解
    • 头文件调用
    • 题目细解
    • 整体代码
  • (三)补充
    • 关于qsort

(一)题目

“真采杯” G题:碧蓝航线 (qsort + 结构体 + 多级排序)_第1张图片
《碧蓝航线》是时下非常热门的一款游戏,是b站代理第二的游戏(第一FGO)。

《碧蓝航线》里面有一个演习模式,这个模式出击需要六艘战舰,前排3艘(前排战舰类型为DD(驱逐),CA(重巡),CL(轻巡)),后排3艘(后排战舰类型BB(战列),CV(航母))。每艘船都有战斗力,一般情况下总战斗力(六艘战斗力的和)和越大,演习的胜率越高。

因为前一段时间海军节,kirito迷上了《碧蓝航线》,他想最大可能性赢得演习的条件下,按阵营喜欢程度上阵战舰(总共4个阵营,白鹰、铁血、重樱、皇家),请你帮他选出6艘战舰,输出总战力和六艘战舰名字,若不行则输出NO。

输入

第1行给定一个正整数n,代表战舰数量(n<=100)

第2行有4个值,代表kirito对4个阵营的喜爱程度(值越大越喜欢,1~4)

接下来n行,每行有4个量,分别为战舰名,长度(<20个字符),战斗力(<10000),类型(DD,CL,CA,BB,CV)和阵营(1白鹰,2铁血,3重樱,4皇家)

输出

如果不行直接输出NO

如果可以第一行输出总战斗力,接下来3行按战斗力高到低输出前排战舰名字
(若两艘战舰战力和阵营相同,则输出按字典序大的输出,提示strcmp函数比较字典序),接下来3行按战斗力高到低输出后排战舰名字(道理同上)

注:可以认为每一艘战舰都是独一无二的,即不会同名

样例

【样例1】
输入
10
2 3 4 1
Enterprise 4000 CV 1
Nagato 4500 BB 3
Azuma 4200 CA 3
Hood 3800 BB 4
Eldridge 3900 DD 1
Yuudachi 3500 DD 3
Kaga 4000 CV 3
Akagi 4000 CV 3
PrinzEugen 4000 CA 2
Z46 3900 DD 2

输出
24600
Azuma
PrinzEugen
Z46
Nagato
Kaga
Akagi

【样例2】
输入
6
1 2 3 4
22 9999 DD 1
33 9999 DD 4
Asuna 8888 CL 3
Minneapolis 8888 CA 1
Yamato 7777 BB 3
Musashi 7777 BB 3

输出
NO

(二)题解

头文件调用

#include 
#include  #用来调用qsort函数
#include  #用来调用strcmp函数

题目细解

1.根据DD(驱逐)CA(重巡)CL(轻巡)BB(战列)CV(航母) 优先进行一个分类——前排与后排

前排 DD(驱逐)CA(重巡)CL(轻巡)
后排 BB(战列)CV(航母)

2.根据战斗力 > 喜爱程度 > 字典排序 进行一个三级排序

(1)写一个结构体来保存三个数据

struct node{
    char name[25];  #保存战舰名
    int zd;         #保存战舰战斗力
    int xa;         #保存战舰的阵营(对应喜爱程度)
} a[105],b[105];    #设置前排、后排两个数组

(2)因为本题要在主函数外调用qsort的排序函数cmp,所以写一个全局变量的数组来保存喜爱程度并使用

int love[5];   #数组长度定义4即可,个人习惯多给几位

3.自行写一个qsort函数要用的cmp函数
(1)使用 -> 写的cmp函数

int comp(const void *x,const void *y){
    struct node *x1 = (struct node *)x;
    struct node *y1 = (struct node *)y;
    if(x1 -> zd != y1 -> zd)    #第一级————比较战斗力
        return x1 -> zd > y1 -> zd ?-1 :1;
    else if(x1 -> xa != y1 -> xa)    #第二级————比较喜爱程度
        return love[x1 -> xa] > love[y1 -> xa] ?-1 :1;
    else if(strcmp(x1 -> name,y1 -> name) != 0)    ##第三级————字典排序
        return -strcmp(x1 -> name,y1 -> name);
    return 0;
}

(2)单纯指针写的cmp函数

int comp(const void *x,const void *y){
	if((*(struct node *)x).zd != (*(struct node *)y).zd)
		return (*(struct node *)x).zd > (*(struct node *)y).zd ?-1 :1;
	else if((*(struct node *)x).xa != (*(struct node *)y).xa)
		return cp[(*(struct node *)x).xa] > cp[(*(struct node *)y).xa] ?-1 :1;
	else return -strcmp((*(struct node *)x).name,(*(struct node *)y).name);
}

4.因为要先根据前后排写一个排序所以我把代码写成了这样

for(int i = 0;i < n;i++){
        scanf("%s %d %s %1d",name1,&zd1,zy,&xa1);
        if(strcmp(zy,"DD") == 0 || strcmp(zy,"CA") == 0 || strcmp(zy,"CL") == 0){
            strcpy(a[suma].name,name1);
            a[suma].zd = zd1;
            a[suma].xa = xa1;
            suma++;
        }
        if(strcmp(zy,"BB") == 0 || strcmp(zy,"CV") == 0){
            strcpy(b[sumb].name,name1);
            b[sumb].zd = zd1;
            b[sumb].xa = xa1;
            sumb++;
        }
    }

整体代码

#include 
#include 
#include 
 
int love[5];
 
struct node{
    char name[25];
    int zd;
    int xa;
} a[105],b[105];
 
int comp(const void *x,const void *y){
    struct node *x1 = (struct node *)x;
    struct node *y1 = (struct node *)y;
    if(x1 -> zd != y1 -> zd)
        return x1 -> zd > y1 -> zd ?-1 :1;
    else if(x1 -> xa != y1 -> xa)
        return love[x1 -> xa] > love[y1 -> xa] ?-1 :1;
    else if(strcmp(x1 -> name,y1 -> name) != 0)
        return -strcmp(x1 -> name,y1 -> name);
    return 0;
}
 
int main()
{
    int suma = 0,sumb = 0;
    int zd1,xa1;
    char name1[25],zy[3];
    int n,x;
    scanf("%d",&n);
    for(int i = 1;i <= 4;i++){
        scanf("%d",&x);
        love[i] = x;
    }
    for(int i = 0;i < n;i++){
        scanf("%s %d %s %1d",name1,&zd1,zy,&xa1);
        if(strcmp(zy,"DD") == 0 || strcmp(zy,"CA") == 0 || strcmp(zy,"CL") == 0){
            strcpy(a[suma].name,name1);
            a[suma].zd = zd1;
            a[suma].xa = xa1;
            suma++;
        }if(strcmp(zy,"BB") == 0 || strcmp(zy,"CV") == 0){
            strcpy(b[sumb].name,name1);
            b[sumb].zd = zd1;
            b[sumb].xa = xa1;
            sumb++;
        }
    }
    if(suma < 3 || sumb < 3) printf("NO");
    else{
        int sums = 0;
        qsort(a,suma,sizeof(a[0]),comp);
        qsort(b,sumb,sizeof(b[0]),comp);
        for(int i = 0;i < 3;i++){
            sums += a[i].zd; 
        }
        for(int i = 0;i < 3;i++){
            sums += b[i].zd; 
        }
        printf("%d\n",sums);
        for(int i = 0;i < 3;i++){
            printf("%s\n",a[i].name);
        }
        for(int i = 0;i < 3;i++){
            printf("%s\n",b[i].name);
        }
    }
    return 0;
}

(三)补充

关于qsort

void qsort(void* base,size_t num,size_t width,int(__cdeclcompare)(const void,const void*));

void* base 待排序数组,排序之后的结果仍放在这个数组中
size_t num 数组中待排序元素数量
size_t width 各元素的占用空间大小(单位为字节)
int(__cdecl* compare)(const void* ,const void* ) 指向函数的指针,用于确定排序的顺序(需要用户自定义一个比较函数)

你可能感兴趣的:(萌新级)