4 条题解

  • 13
    @ 2023-10-2 14:08:34

    来讲讲做题中容易出现的问题。

    首先对于这道题我个人的做法是使用结构体+排序的思路。 目前我遇到的问题都是出在 cmp 函数上,在本题解的讲解也围绕 cmp 函数展开,请使用其它方法的同学们自行类比(反正各种解法其实几乎都是换汤不换药)。

    本人是以 60-70-40-50-90 的顺序错了一圈的,很有经验。

    (本帖又名:我的错误之路)


    首先让我们看看我的结构体定义:

    struct stu{
    	int id;//学号
    	int sc;//总分数
    	int ch;//语文成绩
    }
    

    (不看这个你是看不懂下文的)

    然后来说说问题所在。

    1

    60 分的问题。

    这里贴上错误代码:

    bool cmp(stu a,stu b){
    	if(a.sc==b.sc)return a.id>b.id;
    	return a.sc>b.sc;
    }
    

    这种错法应该出现比较少。

    如果出现这种错误,只能说你有些太粗心了。(但这是我犯的QWQ)

    你在忽视了需在依据学号排序前依据语文成绩排序的同时,还把学号的大小于号写反了欸!

    2

    现在说 70 分,下面贴出 cmp 函数的代码:

    bool cmp(stu a,stu b){
    	if(a.sc==b.sc)return a.id<b.id;
    	return a.sc>b.sc;
    }
    

    这时建议你多读几遍题目

    你甚至忽视了需在依据学号排序前依据语文成绩排序

    3

    之后是 40 分。

    3,2,1,上代码!

    bool cmp(stu a,stu b){
    	if(a.sc==b.sc)return a.ch>b.ch;
    	if(a.ch==b.ch)return a.id<b.id;
    	return a.sc>b.sc;
    }
    

    这个问题出现应相对较少,但它也是最难发现的问题之一。

    在这段代码中,第二个 if 语句不会被运行,对于语文成绩相等的情况,会在第一个 if 语句后返回 false

    对于这个问题,应在第一个 if 语句中加入对于语文成绩是否相等的判断。

    4

    50 分的场合

    bool cmp(stu a,stu b){
    	if(a.sc==b.sc&&a.ch!=b.ch)return a.ch>b.ch;
    	if(a.ch==b.ch)return a.id<b.id;
    	return a.sc>b.sc;
    }
    

    和 40 分的错误性质类似,同样难以发现。

    判断语文应该是在总分相等的前提下。

    5

    最后说 90 分,代码:

    bool cmp(stu a,stu b){
    	if(a.sc==b.sc&&a.ch!=b.ch){
    		return a.ch>b.ch;
    		if(a.ch==b.ch&&a.id!=b.id)return a.id<b.id;
    	}return a.sc>b.sc;
    }
    

    这种情况,首先因为里面那层 ifa.ch==b.ch 会被外面那层 if 筛掉,所以应首先删掉外面那层 if 的第二条判断条件;

    然后把外面那层 if 语句里两条语句交换位置就行了。


    最后,贴上正确的 cmp 函数代码:

    bool cmp(stu a,stu b){
    	if(a.sc==b.sc){
    		if(a.ch==b.ch&&a.id!=b.id)return a.id<b.id;
    		return a.ch>b.ch;
    	}return a.sc>b.sc;
    }
    

    完整代码:

    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    struct stu{
    	int id;
    	int sc;
    	int ch;
    }a[314]={0};
    bool cmp(stu a,stu b){
    	if(a.sc==b.sc){
    		if(a.ch==b.ch&&a.id!=b.id)return a.id<b.id;
    		return a.ch>b.ch;
    	}return a.sc>b.sc;
    }
    int main(){
    	int n,c,m,e;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d%d%d",&c,&m,&e);
    		a[i].id=i;
    		a[i].ch=c;
    		a[i].sc=c+m+e;
    	}
    	sort(a+1,a+n+1,cmp);
    	for(int i=1;i<=5;i++)
    		printf("%d %d\n",a[i].id,a[i].sc);
        return 0;
    }
    

    总结:我在做这题时脑子糊掉了。

    (80 分那次是帮别人调代码)(目前还没调出来,希望好心人帮帮忙

    记得五星好评哦喵~ 谢谢客官啦~

    • @ 2024-10-4 16:12:36

      0分的呢?#include<bits/stdc++.h> using namespace std; struct student{ int xh,yw,sx,yy,zf; }a[305]; bool cmp(student s1,student s2){ if(s1.zfs2.zf){ if(s1.yws2.yw){ return s1.xh<s2.xh; } else return s1.yw>s2.yw; } else return s1.zf>s2.zf; } int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i].xh>>a[i].yw>>a[i].sx>>a[i].yy; a[i].zf=a[i].yw+a[i].sx+a[i].yy; } sort(a+1,a+n+1,cmp); for(int i=1;i<=5;i++)cout<<a[i].xh<<a[i].zf; return 0; }

    • @ 2024-10-22 22:15:59

      爱了爱了

  • 1
    @ 2024-9-30 20:24:59

    认真读题RZDT很重要HZY!!!

    • 0
      @ 2024-10-19 10:31:12

      #include #include using namespace std; typedef long long ll; struct stu{ int id; int sc; int ch; }a[314]={0}; bool cmp(stu a,stu b){ if(a.scb.sc){ if(a.chb.ch&&a.id!=b.id)return a.id<b.id; return a.ch>b.ch; }return a.sc>b.sc; } int main(){ int n,c,m,e; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d%d",&c,&m,&e); a[i].id=i; a[i].ch=c; a[i].sc=c+m+e; } sort(a+1,a+n+1,cmp); for(int i=1;i<=5;i++) printf("%d %d\n",a[i].id,a[i].sc); return 0; }

      • -3
        @ 2023-8-9 17:56:48

        可以在快排那个过程上多加一个变量k,用来表示当前的快排使用的关键字是什么,1表示以总分为关键字,2表示以语文为关键字,3表示以学号为关键字。都是从小到大排序。

        在以总分为关键字排完一遍后,找到总分相同的一些连续位置,将这些位置上的数再以语文为关键字再排一遍,然后再找到连续的总分,语文成绩都相同的位置,将这些位置上的数再以学号为关键字从小到大排。

        代码呈现

        #include<cstdio>
        #include <stdlib.h>
        int n,a[20000][4]; 
        void kp(int l,int r,int k){
            int i = l,j = r,m = a[(i+j)/2][k];
            do
            {
                while (a[i][k] < m) i++;
                while (m < a[j][k]) j--;
                if (i <= j)
                {
                    a[0][1] = a[i][1];
        			a[i][1] = a[j][1];
        			a[j][1] = a[0][1];
                    a[0][2] = a[i][2];
        			a[i][2] = a[j][2];
        			a[j][2] = a[0][2];
                    a[0][3] = a[i][3];
        			a[i][3] = a[j][3];
        			a[j][3] = a[0][3];
                    i++;j--;
                }
            }while (i <= j);
            if (l < j) kp(l,j,k);
            if (i < r) kp(i,r,k);
        }
        void input_data(){
            scanf("%d",&n);
            for (int i = 1;i <= n;i++)
                {
                    int x,y,z;
                    scanf("%d%d%d",&x,&y,&z);
                    a[i][1] = x + y + z;
                    a[i][2] = x;
                    a[i][3] = i;
                }
            kp(1,n,1);
            int i = 1;
            while (i <= n)
                {
                    int j = i+1;
                    while (a[i][1] == a[j][1]) j++;
                    kp(i,j-1,2);
                    i = j;
                }
            i = 1;
            while (i <= n) 
                {
                    int j = i+1;
                    while (a[i][1] == a[j][1] && a[i][2] == a[j][2]) j++;
                    kp(i,j-1,3);
                    i = j;
                }
        }
        void output_ans()
        {
            for (int i = n;i >= n-4;i--)
                printf("%d %d\n",a[i][3],a[i][1]);
        }
        int main(){
            input_data();
            output_ans();
            return 0;
        }
        
        • @ 2024-9-30 20:35:30

          从这段代码可以充分的看出我们这位发表题解的人已经沉迷于自定义函数无法自拔。

      • 1

      信息

      ID
      446
      时间
      1000ms
      内存
      125MiB
      难度
      5
      标签
      递交数
      104
      已通过
      40
      上传者