信奥小白专治:如何用sort实现“两级排序”?——挑战NOIP紫题“清仓甩卖”(四)
搞定动态规划,面对So Easy的小R方案,我却遇到了一个难题:
不会多级排序!
是的,小小的我,只会最简单的sort。
还好,最后我找出儿子之前讲过的一张图解决了这个问题。
题目直达:NOIP2025 清仓甩卖
一、动态规划大法
先来回顾一个我的动态规划大法。
这套大法的整体思路是:
- 遍历所有现价方案。每颗糖果的现价为1或2,有2种可能,n颗糖果的现价方案数就是n个2相乘,共有 2 n 2^n 2n种可能。在第2集说过了,这种方式时间复杂度必爆,但是没关系,我本来也没指望这套大法能拿满分。
- 小R方案的原价。针对每种现价方案,用小R的方案算出买到糖果的原价。
- 动态规划理论原价。针对每种现价方案,用“0-1背包”算法算出理论上能买到的最大原价。
- 原价对比。对比两种原价,如果相同,说明小R的买入方案成立,否则就是不成立。
逻辑多么自洽!除了时间复度稍微高一点儿,简直可以说是完美,真不明白儿子为啥贬低为“爆力破解”。
二、小R方案
2.1 方案逻辑
这套大法的主打歌“动态规划”在第3集已经写完了,本集要来看看小R的买入方案。这个逻辑就简单多了,把前文写的内容直接粘过来:
小R的购买策略:
- 将所有糖果按照性价比从大到小排序,然后依次考虑每一颗糖果。
- 若两颗糖果的性价比相同,会先考虑原价较高的糖果;
- 若两颗糖果的性价比与原价均相同,会先考虑编号较小的糖果。
2.1 两级排序
2.1.1 排序逻辑
虽然买入逻辑很简单,但是需要将糖果重新排序,并且是两级排序:
- 优先按性价比从大到小排序
- 性价比相同,按原价从大到小排序
2.1.2 排序实现研究
以我现有的知识水平,这代码却万万不会写。
之前用过sort函数,但只会用默认的sort(a, b):对[a, b)范围内的元素从小到大排序。这里要从大到小排序,而且有两个规则,怎么个弄法呢?
我只知道要给sort加上第3个参数cmp,表示排序规则,然后还要写一个cmp函数定义比较规则。
忽然间,我灵光一现,想起前几天我家娃好像给我讲过。快,找找手机里的图片!

这段代码和我们想要实现有功能有点类似,排序也有两个规则:
- 优先按x从小到大排序
- 如果x相同,按y从小到大排序
不过,这里面要用到结构体。用结构体其实很好理解,因为要按两个变量排序,这两个变量必须要是数据结构内部的变量,所以要把这两个变量打包到结构体中才行。
2.1.3 排序代码
照猫画虎地写了段代码:
#include<iostream>
#include<algorithm>
using namespace std;
struct candy{
int a, w; //a原价,w现价
};
candy c[100];
bool cmp(candy x, candy y){
double xx=1.0*x.a/x.w;
double yy=1.0*y.a/y.w;
if(xx == yy) return x.a>y.a;
return xx>yy;
}
int main(){
c[0].a=0, c[0].w=0;
c[1].a=1, c[1].w=1;
c[2].a=3, c[2].w=1;
c[3].a=5, c[3].w=2;
sort(c, c+3, cmp);
for(int i=1; i<=3; i++){
printf("%d %d\n", c[i].a, c[i].w);
}
return 0;
}
最开始忘了加
#include<algorithm>,加这个是因为sort()函数是定义在这个库中的,然后还是提示:error: ‘sort’ was not declared in this scope.这才想起来还要加上:
using namespace std;
输出结果:
3 1
1 1
5 2
什么情况?顺序是重排了,可为什么(1, 1)排到了(5, 2)的前面?前者的性价比是1,后者是2.5,所以(5, 2)不是应该排在(1, 1)之前才对吗?
看了半天搞明白了,原来又是sort()函数的参数赋错了。sort(c, c+3, cmp);是对数组的前3个元素(c[0], c[1], c[2])进行排序,根本没含c[3],将参数改为sort(c+1, c+4, cmp);再一测试就非常完美了。
今天虽然没有写出完整的小R方案代码,但是完成了核心的排序部分,可以算是大功告成了。
打完收工!
附:挑战NOIP紫题“清仓甩卖”电视剧全集:
《34行代码搞定了NOIP第一题,我飘了,向“紫题”发起挑战!(一)》

&spm=1001.2101.3001.5002&articleId=158738424&d=1&t=3&u=87212fd2e2224bf3961a003d63cfd434)
3926

被折叠的 条评论
为什么被折叠?



