4 条题解
-
13
来讲讲做题中容易出现的问题。
首先对于这道题我个人的做法是使用结构体+排序的思路。 目前我遇到的问题都是出在
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; }
这种情况,首先因为里面那层
if
的a.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 分那次是帮别人调代码)(目前还没调出来,希望好心人帮帮忙)记得五星好评哦喵~ 谢谢客官啦~
-
0
#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
可以在快排那个过程上多加一个变量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; }
- 1
信息
- ID
- 446
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 104
- 已通过
- 40
- 上传者