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其实还是很容易的。
几种不合法的输入情况:
- 字符串任意位置含有字母
- 仅由数字组成但有不止一个小数点,或者小数点出现在首字符位置
- 小数部分超过2位
- 绝对值大于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 N−1次,在个位出现 N − 1 N-1 N−1次,那么这个数对于总和的贡献就是 e l e m V a l u e × ( 10 + 1 ) × ( N − 1 ) elemValue\times(10+1)\times(N-1) elemValue×(10+1)×(N−1),明白了这个原理之后,求组合数的和就很容易了。
源代码
#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;
}