题目地址:https://www.luogu.com.cn/problem/P1781

题目描述:地球历公元 6036 年,全宇宙准备竞选一个最贤能的人当总统,共有 n 个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统。

输入格式:第一行为一个整数 n,代表竞选总统的人数。

接下来有 n 行,分别为第一个候选人到第 n 个候选人的票数。第一个人的票数是1,往后依次叠加。

输出格式:共两行,第一行是一个整数 m,为当上总统的人的号数。第二行是当上总统的人的选票。

提示:票数可能会很大,可能会到100位数字。全宇宙有这么多人?宇宙总管啊,你确实要实行计划生育的基本策略了,你看人这么多,搞得我还要用高精做这道题!,1<=n<=20。

这是一道排序和高精同时使用的题目。一般这种需要对多种元素进行排序的题目(比如说本题的m(号数)和n(票数)),可以考虑用结构体做。于是,我创建了一个表示候选人信息的结构体:

struct data
{
char number[];//票数
int rank;//号
void operator=(data& a)//表示data对于等于号的运算法则
{
strcpy(this->number,a.number);//this表示调用此函数的对象本身,是一个指针
this->rank=a.rank;
}
}a[];

其中operator=是最需要讲一讲的。

operator是一种特殊的函数,这种函数的命名是operator后跟一个运算符(中间没有空格)。它只能在一个结构体(或面向对象编程里的“类”)中定义。这种函数是为了明确结构体中运算符的运算法则的。一般的加减乘除等各种运算符,只适用于int等数字类型。如果让一个结构体(如本题的data)使用运算符:

int a,b=;
a=b;//b的值被赋给了a
data c,d;
c=d;//计算机:什么意思?该怎么执行赋值?你告诉我呀!

很明显编译器并不知道怎么执行赋值操作,会报错。

那么,只能让我们告诉编译器了!

上述operator=(data& a)函数表示等号的左右边都是data类型时的操作。还需要介绍一下this指针。它表示使用这个函数的对象本身。举例说明:

struct my_str
{
int num;
void output()
{
cout<<this->num;
}
void compare(my_str other)
{
if(this->num<other.num) cout<<"Smaller";
else if(this->num==other.num) cout<<"Same";
else cout<<"Bigger";
}
};
int main()
{
my_str a,b;
a.num=;
b.num=;
a.output();//a是操纵函数的结构体对象本身,此时output里的this就是a。输出:1
b.compare(a);//此时this是b。由于2>1,所以输出:Bigger。
}

this看起来好像没什么卵用,只是起到让代码意思更清晰而已。但是随着编程的深入,this指针将会很有用。

operator函数可以定义各种类型的运算符,不仅是一般的加减乘除和赋值,还有关系运算符,逻辑运算符,特殊运算符等等(具有极重要意义的运算符除外,比如说作用域解析运算符::和宏符号#)。值得一提的是,由于等号在一般情况下不返回值,所以它被声明为void函数。同理,逻辑运算符因为要返回真或假值以供if或while使用,所以operator!,operator&&和operator||应声明为返回bool。参数也要注意,关系运算符、赋值运算符、&&和||在一般情况下有两个操作数,所以它们的operator函数应该有且只有一个参数表示右操作数(左操作数一般就是调用函数的对象本身,不用再声明)。

回到原题。我的想法是用选择排序,因此需要比较。然而高精度数字本质上是字符串,字符串无法直接用大于小于等于来比较,所以我写了一个比较高精数的函数:

#define LEFT_IS_BIGGER false//为了便于理解
#define RIGHT_IS_BIGGER true
bool WHO_IS_BIGGER(char* a,char* b)
{
int lena=strlen(a);
int lenb=strlen(b);
if(lena!=lenb)//位数不一样,直接确定谁大谁小
{
if(lena>lenb) return LEFT_IS_BIGGER;
else return RIGHT_IS_BIGGER;
}
else
{
for(int i=;i<lena;i++)
{
if(a[i]/*-48*/>b[i]/*-48*/) return LEFT_IS_BIGGER;//从高位向低位,若遇到不同的数字就可以直接判断大小
else if(a[i]<b[i]) return RIGHT_IS_BIGGER;
else continue;
}
}
}

为什么a[i]后面有个注释的-48?他的目的是将字符的0123456789转换为数字的0123456789(0的ASCII码是48)。但其实没必要这样做。可以想到,两个字符的数字比大小和两个转换后的数字比大小返回的结果是一样的。于是我把它注释掉了。

对了,选择排序还需要交换(swap函数),但它只适用于int,所以我写了一个交换data对象的函数:

void my_swap(data& a,data& b)
{
data temp=a;
a=b;
b=temp;
}

和int的swap一样,只是int全部换成了data而已。这里operator=就派上用场了。这个函数里的等号都调用了operator=函数,非常自然,没有一点编译器错误,我们不需要再额外定义一个对于data的赋值函数,用现成的等号就行,简明易懂。这就是operator函数的好处。

最后就是主函数了。道理和选择排序的原理一样,若不理解选择排序,可以查阅相关百科或书籍。

int main()
{
int n;
cin>>n;
for(int i=;i<n;i++)
{
scanf("%s",a[i].number);
a[i].rank=i+;
}
for(int i=;i<n;i++)
{
for(int j=i+;j<n;j++)
{
if(WHO_IS_BIGGER(a[i].number,a[j].number)==RIGHT_IS_BIGGER)
{
my_swap(a[i],a[j]);
}
}
}
cout<<a[].rank<<endl;
printf("%s",a[].number);
}

P1781 宇宙总统的更多相关文章

  1. 洛谷 P1781 宇宙总统

    P1781 宇宙总统 题目背景 宇宙总统竞选 题目描述 地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统. 输入输出 ...

  2. (大数 string easy。。。)P1781 宇宙总统 洛谷

    题目背景 宇宙总统竞选 题目描述 地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统. 输入输出格式 输入格式: pr ...

  3. 洛谷——P1781 宇宙总统

    https://www.luogu.org/problem/show?pid=1781 题目背景 宇宙总统竞选 题目描述 地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人 ...

  4. (Java实现) 洛谷 P1781 宇宙总统

    题目背景 宇宙总统竞选 题目描述 地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统. 输入输出格式 输入格式: pr ...

  5. 洛谷 P1781 宇宙总统:sort(string)

    题目描述 地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统. 输入输出格式 输入格式: 第一行为一个整数n,代表竞选 ...

  6. 洛谷P1781 宇宙总统【排序+字符串】

    地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统. 输入输出格式 输入格式: president.in 第一行为一个 ...

  7. 洛谷P1781——宇宙总统(高精度排序)

    题目描述 地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人竟选总统,现在票数已经统计完毕,请你算出谁能够当上总统. 输入输出格式 输入格式: 第一行为一个整数n,代表竞选 ...

  8. 洛谷 P1059明明的随机数 & P1068分数线划定 & P1781宇宙总统

    题目:https://www.luogu.org/problemnew/show/P1059 思路:STL中的set使用. //#include<bits/stdc++.h> #inclu ...

  9. 洛谷P1781宇宙总统题解

    题目 此题原本是一个简单的排序,但因为数据范围的限制,所以变成了一个需采用字符串排序的题目,接下来我将给大家讲一下如何字符串排序. 首先先判断为位数上是否相同,如果不同再比较那一位的数就可以了 #in ...

随机推荐

  1. softmax、交叉熵

    Softmax是用于分类过程,用来实现多分类的 它把一些输出的神经元映射到(0-1)之间的实数,并且归一化保证和为1,从而使得多分类的概率之和也刚好为1. Softmax可以分为soft和max,ma ...

  2. springMVC:SSM整合

    环境要求 环境: IDEA MySQL 5.7.19 Tomcat 9 Maven 3.6 要求: 需要熟练掌握MySQL数据库,Spring,JavaWeb及MyBatis知识,简单的前端知识: 数 ...

  3. JavaSE--日志

    参考 https://www.cnblogs.com/hanszhao/p/9754419.html https://www.cnblogs.com/chenhongliang/p/5312517.h ...

  4. Kubernetes-基于helm安装部署高可用的Redis及其形态探索(二)

    上一章,我们通过实践和其他文章的帮助,在k8s的环境安装了redis-ha,并且对其进行了一些实验来验证他的主从切换是否有效.本篇中将会分析,究竟是如何实现了redis-ha的主从切换,以及其与K8S ...

  5. Airflow 使用 Celery 时,如何添加 Celery 配置

    背景 前段时间我选用了 Airflow 对 wms 进行数据归档,在运行一段时间后,经常发现会报以下错误: [-- ::,: WARNING/ForkPoolWorker-] Failed opera ...

  6. 十四、CI框架之数据库以参数形式插入操作

    一.代码如下: 二.使用浏览器打开 三.我们查看数据库,被成功插入数据 不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码打赏任意金额给作者(微信号:382477247)哦,谢谢.

  7. slf4j NoSuchMethodError 错误 ---- 版本冲突

    java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/Stri ...

  8. linux常用命令之------文件操作、文件查看、权限、打包压缩

    1.一般公司把linux作为自己的应用服务器,将应用和服务器部署在上面 2.测试一般用来打包.压缩.查日志,写一个简单的shell 获得linux服务器的方式 a:网上租一台云服务器 b:安装vmwa ...

  9. js 动态添加元素 删除元素逻辑

    js 动态添加元素 删除元素逻辑 var obox=document.getElementById("box"); oadd.onclick=function(){ var odi ...

  10. 洛谷 P1018乘积最大

    题目描述 今年是国际数学联盟确定的“20002000――世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰9090周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友 ...