[PAT Basic Level] 1053~1057

1053. 住房空置率

题目分析:

实现起来不算太复杂的一道题,不过要认真审题,弄明白题目的意思。
分别读取记录好用电量的阈值以及观察期的阈值,用一个变量count统计某户用电低于阈值的天数。然后对每一户依次进行的数据读取,如果某一天的用电量低于用电阈值就把天数+1,这样统计出该户用电少于阈值的天数,如果小于一半,再比较观察的天数是否超过了天数的阈值(注意是观察天数而不是用电量低于阈值天数),来判断是空置还是可能空置。

源代码

#include <stdio.h>

int main()
{
    int housNumber,thresh_days;
    double thresh_usage;
    int ob_days,may_vacNumber=0,vacNumber=0; //观测天数、可能空置房间数、空置房间数
    scanf("%d %lf %d",&housNumber,&thresh_usage,&thresh_days);
    for(int i=0;i<housNumber;++i){
        scanf("%d",&ob_days);
        double *data=new double[ob_days];
        int count=0;
        for(int i=0;i<ob_days;++i){
            scanf("%lf",&data[i]);
            if(data[i]<thresh_usage)  //低于用电阈值
                count++;
        }
        if(count>(ob_days>>1)){
            if(ob_days>thresh_days) vacNumber++;
            else may_vacNumber++;
        }
        delete []data;
    }
    double may_vacRatio,vacRatio;
    may_vacRatio=100*(double)may_vacNumber/housNumber;
    vacRatio=100*(double)vacNumber/housNumber;
    printf("%.1f%% %.1f%%",may_vacRatio,vacRatio);
    return 0;
}

1054. 求平均值

题目分析:

这类题难度一般不大,主要困难在于判断的条件比较复杂,写这类题一定要耐心,仔细考虑各种情况,只要沉住气踏踏实实编写,会发现AC其实还是很容易的。

几种不合法的输入情况:

  1. 字符串任意位置含有字母
  2. 仅由数字组成但有不止一个小数点,或者小数点出现在首字符位置
  3. 小数部分超过2位
  4. 绝对值大于1000

基本上把这几种情况都考虑进去了,代码就能通过。另外还是要注意一下负数的处理。而且各种判断比较繁琐,放在主函数里看起来很容易乱,还是建议分出一个函数用来判断输入是否合法。

源代码

#include <stdio.h>
#include <cmath>
#include <cctype>
double isValid(char*a,int len);  //输入不合法时返回-10001
int main()
{
    int testNumber;
    scanf("%d",&testNumber);
    getchar();  //读取换行符
    char input[100];  //用100个字符存储单个输入
    int count,total=0; //记录单个字符串的长度以及有效输入的个数
    double sum=0.0;
    while(testNumber--){
        count=0;
        while((input[count]=getchar())!=' '&&input[count]!='\n') //读到空格或者行尾结束
            count++;
        input[count]='\0';  //添上空字符
        double judge=isValid(input,count);
        if(judge<-1000)
            printf("ERROR: %s is not a legal number\n",input);
        else{ //输入有效
            total++;
            sum+=judge;
        }
    }
    if(total>1) printf("The average of %d numbers is %.2f",total,sum/total);
    else if(total==1) printf("The average of 1 number is %.2f",sum);
    else printf("The average of 0 numbers is Undefined");
    return 0;
}
double isValid(char *arr,int len)
{
    int pnum=0,posit,extra=1; //记录小数点个数及位置,extra表示整数位相应的10的幂
    double result=0.0;
    for(int i=0;i<len;++i){
        if(isalpha(arr[i])) return -1001.0;
        else if(arr[i]=='.') {pnum++;posit=i;}
    }
    if(pnum>1||(pnum==1&&len-posit>3)||(pnum==1&&posit==0)) return -1001.0; //多于一个小数点或者小数点后有2位以上或第一位就是小数点,不合法
    else if(pnum==1){
        int i=posit-1;
        double bonus=0.1;
        while(i>0){
            result+=(double)(arr[i]-'0')*extra;  //主要考虑到乘法计算溢出,故转换为double
            extra*=10;
            i--;
        }
        for(i=posit+1;i<len;++i){  //加入小数部分
            result+=(arr[i]-'0')*bonus;
            bonus/=10;
        } 
    }
    else{ //无小数点,为整
        for(int i=len-1;i>0;--i){
            result+=(arr[i]-'0')*extra;
            extra*=10;
        }
    }
    if(arr[0]=='-'){ result=-result;}
    else {result+=(double)(arr[0]-'0')*extra;}
    if(fabs(result)>1000.0) return -1001.0;
    return result;
}

1055. 集体照

题目分析:

这道题主要需要做的工作一个是根据身高和字母序排好序,另一部分就是按照排列的规则一行行排序输出了。
第一步的工作我们可以借助algorithm头文件里的sort函数,方便地进行排序,写到这里相信大家都已经对sort函数比较熟悉,就不赘述了。
在每行输出时,每一行排好最高者后,按降序依次往左边和右边插入,这里我采用了一个bool变量标记该往左插还是往右。每次拍好一行后立即输出即可。
这题我没想到什么巧妙的方法,踏踏实实编写就好。

源代码

#include <stdio.h>
#include <algorithm>
#include <cstring>
typedef struct info
{
    char name[9];
    int height;
}Info;

bool cmp(const Info&p1,const Info& p2){ 
    if(p1.height!=p2.height) return p1.height>p2.height;
    return strcmp(p1.name,p2.name)<0;
    } //按身高降序排列
void printLine(Info* arr,int begin,int end){ //按给定的范围输出
    int n=end-begin+1;
    Info* arrange=new Info[n];
    int hiPosit=n>>1; 
    arrange[hiPosit]=arr[begin];
    int left=1,right=1;
    bool isOdd=true; //奇偶标志,用来判断应该站左边还是右边
    for(int i=begin+1;i<=end;++i){
        if(isOdd){
            arrange[hiPosit-left]=arr[i];
            left++;
            isOdd=false;
        }
        else{
            arrange[hiPosit+right]=arr[i];
            right++;
            isOdd=true;
        }
    }
    for(int i=0;i<n;++i){
        if(i) printf(" ");
        printf("%s",arrange[i].name);
    }
    printf("\n");
    delete []arrange;
}


int main()
{
    int num,line;
    scanf("%d %d",&num,&line);
    Info* person=new Info[num];
    for(int i=0;i<num;++i)
        scanf("%s %d",person[i].name,&person[i].height);
    std::sort(person,person+num,cmp);
    int numPerRow=num/line;
    int last=num-numPerRow*(line-1);
    printLine(person,0,last-1);
    int begin=last;
    while(begin<num){
        printLine(person,begin,begin+numPerRow-1);
        begin+=numPerRow;
    }
    delete []person;
    return 0;
}

1056. 组合数的和

题目分析:

这道题进行一些简单分析就容易发现,假设给出的序列有 N N N个数,那么序列中任意一个数,都会在十位出现 N − 1 N-1 N1次,在个位出现 N − 1 N-1 N1次,那么这个数对于总和的贡献就是 e l e m V a l u e × ( 10 + 1 ) × ( N − 1 ) elemValue\times(10+1)\times(N-1) elemValue×(10+1)×(N1),明白了这个原理之后,求组合数的和就很容易了。

源代码

#include <stdio.h>

int main()
{
    int num;
    int value;
    scanf("%d",&num);
    int sum=0;
    for(int i=0;i<num;++i){
        scanf("%d",&value);
        sum+=value;
    }
    sum*=11*(num-1);
    printf("%d",sum);
    return 0;
}

1057. 数零壹

题目分析:

这道题求和部分就不赘述了,依次读取,遇到字母后统一转换成大或者小写再求出对应值即可。
再判断二进制多少0或者1时,可以通过右移一位一位地判断,如果当前是偶数,则末位为0,否则为1,以此这样,每次右移一位,再判断,直到数变为0即可。

源代码

#include <stdio.h>
#include <cctype>
int main()
{
    int sum=0;
    int digit;
    while((digit=getchar())!='\n')
        if(isalpha(digit)) sum+=toupper(digit)-'A'+1;
    int zeroNum=0,oneNum=0;
    while(sum){
        if(sum%2==0) zeroNum++;
        else oneNum++;
        sum>>=1;
    }
    printf("%d %d",zeroNum,oneNum);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值