当总统

本文介绍了一道关于小明竞选丑国总统的算法题,解析了如何通过计算获得当选所需的最少选民支持数量,并提供了C++实现代码。

当总统

时间限制: 1 Sec 内存限制: 32 MB


题目描述

小明想当丑国的总统,丑国大选是按各州的投票结果来确定最终的结果的,如果得到超过一半的州的支持就可以当选,而每个州的投票结果又是由该州选民投票产生的,如果某个州超过一半的选民支持小明,则他将赢得该州的支持。现在给出每个州的选民人数,请问小明至少需要赢得多少选民的支持才能当选?

输入

输入包含多组测试数据。
每组数据的第一行是一个整数N(1<=N<=101),表示丑国的州数,当N=0时表示输入结束。
接下来一行包括N个正整数,分别表示每个州的选民数,每个州的选民数不超过100。

输出

对于每组数据输出一行,表示小明至少需要赢得支持的选民数。

样例输入

3
5 7 5
0

样例输出

6

题意概括

拉选票,给出n个州和每个州的总人数,能够选上总统就必须得到超过一半州的支持,当一个支持的人数超过一半的时候表示这个周支持,问当上总统所需要啦的最小的选票;

解题思路

首先将每一个州的信息按照人数从小到大排序,找出超过一半州的州的数量,然后最前超过一半州的人数的超过一半的人数进行求和。

代码

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;

int main ()
{
    int n,m,i,j,sum;
    int a[1100];
    while(~scanf("%d",&n),n!=0){
        for(i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        sum=0;
        m=n/2;
        m++;
        sort(a,a+n);
        for(i=0;i<m;i++){
            sum+=a[i]/2;
            sum++;
        }
        printf("%d\n",sum);
    }
    return 0;
}

转载于:https://www.cnblogs.com/lanaiwanqi/p/10445720.html

<think>好的,我现在需要解决用户关于“宇宙总统 P1781”题目的C语言实现问题。用户提到使用了qsort、strcmp、大数比较和结构体排序,但遇到了错误。首先,我得仔细分析题目要求和用户可能的代码问题。 题目应该是要求从多个候选人的得票数中选出最大的,因为得票数可能非常大,所以需要用字符串处理大数比较。用户可能用结构体存储候选人信息,然后使用qsort进行排序,但比较函数可能有问题。 首先,用户可能尝试直接使用strcmp来比较字符串,但得票数字符串的长度不同时,比如"123"和"45",strcmp会比较字符的ASCII值,而"123"比"45"长,但实际数值更大。然而,strcmp在长度不同的情况下,会先比较前面的字符,如果前面的字符都相同,长度长的更大。但这里得票数是数字字符串,所以需要先比较长度,长度长的数值大;长度相同的话,再用strcmp逐位比较。 所以,用户的比较函数可能没有处理长度不同的情况,直接用了strcmp,导致排序错误。例如,当比较"1000"和"999"时,strcmp会比较'1'和'9',因为'1'的ASCII小于'9',所以会认为"1000"更小,但实际上数值更大。这时候就需要先比较字符串长度,长度更长的数值更大,只有长度相同的时候才用strcmp。 接下来,用户的结构体可能包含得票数字符串和编号,qsort的比较函数需要自定义。用户可能在比较函数中直接返回strcmp的结果,但正确的做法是先比较字符串长度,再比较字符串内容。 另外,用户可能没有正确处理字符串的存储,比如没有分配足够的内存,或者在读取输入时出现错误,导致字符串没有正确终止或者越界。例如,使用scanf读取字符串时没有限制长度,导致缓冲区溢出。 还可能的问题是在使用qsort时,结构体数组的指针传递不正确,或者元素大小参数设置错误,导致排序混乱。例如,结构体的sizeof没有正确计算,或者交换了元素的位置。 此外,用户可能没有考虑到输入数据中有前导零的情况,比如得票数是"00123",这时候比较时需要处理,但根据题目描述,可能输入的数据都是有效的,没有前导零,或者需要去除前导零后再比较。如果题目允许前导零,那么比较时也需要先处理掉这些零,否则会影响比较结果。 还有一个可能的问题是,用户的比较函数没有返回正确的int类型值,导致qsort行为异常。例如,比较函数返回了strcmp的结果,但可能需要根据长度调整返回值。比如,当str1的长度大于str2时,应该返回正数,反之返回负数,长度相同再调用strcmp。 综上所述,用户的问题可能集中在比较函数的实现上,没有正确处理字符串长度,以及可能的输入处理错误。需要指导用户修改比较函数,先比较字符串长度,再比较字符串内容,并确保输入处理正确,结构体排序正确。</think>### 宇宙总统 P1781 题解分析与优化 #### 一、常见错误分析 1. **直接使用`strcmp`比较数值字符串** 错误示例: ```c int cmp(const void* a, const void* b) { return strcmp(((Node*)a)->num, ((Node*)b)->num); } ``` 问题:当比较`"1000"`和`"999"`时,`strcmp`会错误判定`"1000" < "999"`(因为`'1' < '9'`的ASCII值比较) 2. **未处理字符串长度差异** 错误现象:`"12345"`会被误判小于`"9"` 3. **结构体定义不当** ```c typedef struct { char num[1000]; // 长度不足导致溢出 int id; } Node; ``` #### 二、正确实现方案 ##### 关键点:大数比较算法 1. **比较规则**: - 字符串长度不同时,长度大的数值更大 - 长度相同时,按字典序比较 2. **优化后的比较函数**: ```c typedef struct { char num[1005]; // 预留N+5空间 int id; } Node; int cmp(const void* a, const void* b) { Node *p = (Node*)a, *q = (Node*)b; int len1 = strlen(p->num), len2 = strlen(q->num); // 长度不同时直接比较长度 if(len1 != len2) return len2 - len1; // 注意是降序排列 // 长度相同时用strcmp比较(注意符号取反) return -strcmp(p->num, q->num); } ``` ##### 完整代码框架 ```c #include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct { char num[1005]; int id; } Node; int cmp(const void* a, const void* b) { /* 上述比较函数实现 */ } int main() { int n; scanf("%d", &n); Node arr[n]; for(int i=0; i<n; i++){ scanf("%s", arr[i].num); arr[i].id = i+1; // 题目要求序号从1开始 } qsort(arr, n, sizeof(Node), cmp); printf("%d\n%s", arr[0].id, arr[0].num); return 0; } ``` #### 三、性能优化建议 1. **内存预分配**:使用固定长度数组而非动态内存 2. **输入优化**:`scanf`比`gets`更安全 3. **减少拷贝**:结构体直接存储原始数据 #### 四、特殊测试用例 ```text // 输入1 3 9876543210 12345678901 9999999999 // 输出1 2 12345678901 // 输入2(等长比较) 5 31415926535 27182818284 11235813213 14142135623 16180339887 // 输出2 1 31415926535 ``` #### 五、错误排查清单 1. 检查输入字符串是否包含前导零 2. 验证结构体数组是否越界(题目最大N=20) 3. 确认`qsort`的`sizeof`参数是否正确 4. 测试边界值:最大长度字符串比较 --相关问题-- 1. 如何处理超长字符串(超过1000位)的比较? 2. 为什么不能用`memcmp`代替`strcmp`进行数值比较? 3. 如何实现多条件排序(如数值相同按ID升序)? 4. `qsort`函数的时间复杂度如何影响本题性能? [^1]: C11标准规定字符串比较基于字符的ASCII值顺序 [^2]: 多数编译器实现返回-1/0/1,但标准允许返回任意符号正确的整数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值