【C语言】九度OJ机试题源码
题库:http://ac.jobdu.com/tutorialproblems.php
题号1202排序
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<time.h> 4 5 /*递增排序*/ 6 int compInc(const void *a,const void *b) 7 { 8 return *(int *)a-*(int *)b; 9 } 10 11 int main() 12 { 13 int n,*A; 14 while(scanf("%d",&n)!=EOF) 15 { 16 A = (int *)malloc(sizeof(int)*n); 17 int i; 18 if(n<1||n>100) 19 return 0; 20 else 21 { 22 for(i=0;i<n;i++) 23 { 24 scanf("%d",A+i); 25 } 26 qsort(A,n,sizeof(*A),compInc); 27 for(i=0;i<n;i++) 28 { 29 printf("%d ",*(A+i)); 30 } 31 printf("\n"); 32 } 33 } 34 return 0; 35 }
题号1061成绩排序
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 typedef struct S{ 6 char name[20]; 7 int age; 8 int grade; 9 }student; 10 11 int cmp(const void *a,const void *b) //实现比较规则 12 { 13 student * aa = (student *)a; 14 student * bb = (student *)b; 15 if(aa->grade!=bb->grade) 16 return aa->grade-bb->grade;//若分数不相同则分数低者在前 17 else if(strcmp(aa->name,bb->name)!=0) 18 return (strcmp(aa->name,bb->name));//若分数相同则名字字典序小者在前 19 else return aa->age-bb->age;//若名字也相同则年龄小者在前 20 } 21 22 int main() 23 { 24 int n; 25 int i; 26 student a[1000]; 27 while(scanf("%d",&n)!=EOF) 28 { 29 for(i=0;i<n;i++) 30 { 31 scanf("%s%d%d",a[i].name,&a[i].age,&a[i].grade); 32 } 33 qsort(a,n,sizeof(student),cmp); 34 for(i=0;i<n;i++) 35 { 36 printf("%s %d %d\n",a[i].name ,a[i].age ,a[i].grade ); 37 } 38 } 39 return 0; 40 }
题号1061成绩排序(与上题定义结构的方法不同)
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 struct S{ 6 char name[20]; 7 int age; 8 int grade; 9 }student[1000]; 10 11 int cmp(const void *a,const void *b) //实现比较规则 12 { 13 struct S *aa = (struct S *)a; 14 struct S *bb = (struct S *)b; 15 int tmp=strcmp(aa->name,bb->name); 16 if(aa->grade!=bb->grade) return aa->grade>bb->grade?1:-1;//若分数不相同则分数低者在前 17 else if(tmp!=0) return tmp;//若分数相同则名字字典序小者在前 18 else return aa->age<bb->age?1:-1;//若名字也相同则年龄小者在前 19 } 20 21 int main() 22 { 23 int n; 24 int i; 25 while(scanf("%d",&n)!=EOF) 26 { 27 for(i=0;i<n;i++) 28 { 29 scanf("%s%d%d",student[i].name,&student[i].age,&student[i].grade); 30 } 31 qsort(student,n,sizeof(student[0]),cmp); 32 for(i=0;i<n;i++) 33 { 34 printf("%s %d %d\n",student[i].name ,student[i].age ,student[i].grade ); 35 } 36 } 37 return 0; 38 }
题号1185特殊排序
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 int cmp(const void *a,const void *b) 5 { 6 return *(int *)a-*(int *)b; 7 } 8 9 int main() 10 { 11 int n,i,*A; 12 while(scanf("%d",&n)!=EOF) 13 { 14 A = (int *)malloc(sizeof(int)*n); 15 for(i=0;i<n;i++) 16 { 17 scanf("%d",A+i); 18 } 19 if(n==1) 20 printf("%d\n-1",*A); 21 else 22 { 23 qsort(A,n,sizeof(*A),cmp); 24 printf("%d\n",*(A+n-1)); 25 for(i=0;i<n-2;i++) 26 { 27 printf("%d ",*(A+i)); 28 } 29 printf("%d",*(A+n-2));//防止多输出一个空格 30 } 31 printf("\n");//这个换行符使光标移到下一行 没有它会wrong answer 32 } 33 return 0; 34 }
题号1023EXCEL排序
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 typedef struct S{ 6 char name[20]; 7 char sno[20]; 8 int score; 9 }student; 10 11 12 int cmp1(const void *a,const void *b) 13 { 14 student *aa = (student *)a; 15 student *bb = (student *)b; 16 return(strcmp(aa->sno,bb->sno)); 17 } 18 19 int cmp2(const void *a,const void *b) 20 { 21 student *aa = (student *)a; 22 student *bb = (student *)b; 23 if(strcmp(aa->name,bb->name)!=0) 24 return(strcmp(aa->name,bb->name)); 25 else return(strcmp(aa->sno,bb->sno)); 26 } 27 28 int cmp3(const void *a,const void *b) 29 { 30 student *aa = (student *)a; 31 student *bb = (student *)b; 32 if(aa->score!=bb->score) 33 return aa->score-bb->score; 34 else return(strcmp(aa->sno,bb->sno)); 35 } 36 37 int main() 38 { 39 int n,C; 40 int i,seq=0; 41 while(scanf("%d",&n)!=EOF) 42 { 43 student *a; 44 a = (student *)malloc(sizeof(student)*n); 45 scanf("%d",&C); 46 if(n!=0) 47 { 48 seq++; 49 for(i=0;i<n;i++) 50 { 51 scanf("%s%s%d",(*(a+i)).sno,(*(a+i)).name,&(*(a+i)).score); 52 } 53 switch(C) 54 { 55 case 1: 56 qsort(a,n,sizeof(student),cmp1); 57 break; 58 case 2: 59 qsort(a,n,sizeof(student),cmp2); 60 break; 61 case 3: 62 qsort(a,n,sizeof(student),cmp3); 63 break; 64 default:break; 65 } 66 } 67 else break; 68 printf("Case %d:\n",seq); 69 for(i=0;i<n;i++) 70 { 71 printf("%s %s %d\n",(*(a+i)).sno,(*(a+i)).name,(*(a+i)).score); 72 } 73 } 74 return 0; 75 }
由于之前很猪,连题意都没看懂,于是这个题还写了一个一下版本二,一次性输入一次性输出
题号1023EXCEL排序之一次性输入输出
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 typedef struct S{ 6 char name[20]; 7 char sno[20]; 8 int score; 9 }student; 10 11 12 int cmp1(const void *a,const void *b) 13 { 14 student *aa = (student *)a; 15 student *bb = (student *)b; 16 return(strcmp(aa->sno,bb->sno)); 17 } 18 19 int cmp2(const void *a,const void *b) 20 { 21 student *aa = (student *)a; 22 student *bb = (student *)b; 23 if(strcmp(aa->name,bb->name)!=0) 24 return(strcmp(aa->name,bb->name)); 25 else return(strcmp(aa->sno,bb->sno)); 26 } 27 28 int cmp3(const void *a,const void *b) 29 { 30 student *aa = (student *)a; 31 student *bb = (student *)b; 32 if(aa->score!=bb->score) 33 return aa->score-bb->score; 34 else return(strcmp(aa->sno,bb->sno)); 35 } 36 37 int main() 38 { 39 int n[100]; 40 int C[100]; 41 int i=0,j=0,k=0,l=0; 42 student *a; 43 a = (student *)malloc(sizeof(student)*1000); //student a[1000]; 44 while(scanf("%d%d",&n[k],&C[k])!=EOF && n[k]!=0) 45 { 46 j=i; 47 for(;i<n[k]+j;i++) 48 { 49 scanf("%s%s%d",(*(a+i)).sno,(*(a+i)).name,&(*(a+i)).score); 50 } 51 switch(C[k]) 52 { 53 case 1: 54 qsort(a+j,n[k],sizeof(student),cmp1); 55 break; 56 case 2: 57 qsort(a+j,n[k],sizeof(student),cmp2); 58 break; 59 case 3: 60 qsort(a+j,n[k],sizeof(student),cmp3); 61 break; 62 default:break; 63 } 64 k++; 65 } 66 l=k;j=0; 67 for(k=0;k<l;k++) 68 { 69 printf("Case %d:\n",C[k]); 70 for(i=0;i<n[k];i++,j++) 71 { 72 printf("%s %s %d\n",(*(a+j)).sno,(*(a+j)).name,(*(a+j)).score); 73 } 74 } 75 return 0; 76 }
其中第69行还写错了,题目要求输出测试用例的组数,我写成了C的值...不过在上面那个正确的例子里已经改过来了,这里就不改了
确实这样输出要麻烦一些,写得也有些乱。其中输入的所有struct都是连续的,但输出用变量控制,分开输出。
题号1054字符串内排序
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 int cmp(const void *a,const void *b) 5 { 6 return *(char *)a-*(char *)b; 7 } 8 9 int main() 10 { 11 int n,i; 12 char *A; 13 A = (char *)malloc(sizeof(char)*200); 14 while(scanf("%s",A)!=EOF)//尽量不要用gets和puts 15 { 16 for(i=0;A[i]!='\0';i++); 17 qsort(A,i,sizeof(char),cmp); 18 n=i; 19 for(i=0;i<n;i++) 20 { 21 printf("%c",A[i]); 22 } 23 printf("\n"); 24 } 25 }
题号1069日期差值
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 int days[12][2]={ 5 {31,31}, 6 {28,29}, 7 {31,31}, 8 {30,30}, 9 {31,31}, 10 {30,30}, 11 {31,31}, 12 {31,31}, 13 {30,30}, 14 {31,31}, 15 {30,30}, 16 {31,31} //对每个月的天数进行初始化 17 }; 18 19 int isleapyear(int a) //判断是不是闰年 20 { 21 if((a%100!=0 && a%4==0) || a%400==0) 22 return 1; 23 else return 0; 24 } 25 26 int absolute(int a) 27 { 28 return a>0?a:-a; 29 } 30 31 int main() 32 { 33 int i; 34 int YEAR[5000]; //初始化5000年 35 int day1=0,day2=0; //算出两个日子距离0001年1月1日有多少天(总天数) 36 37 char A[9],B[9]; 38 int yearA,monthA,dayA; 39 int yearB,monthB,dayB; 40 41 /*算出每年有多少天*/ 42 for(i=1;i<5000;i++) 43 { 44 if(isleapyear(i)) 45 YEAR[i]=366; 46 else YEAR[i]=365; 47 } 48 49 while(scanf("%s",A)!=EOF && scanf("%s",B)!=EOF) 50 { 51 yearA=(A[0]-'0')*1000 + (A[1]-'0')*100 + (A[2]-'0')*10 + (A[3]-'0'); 52 monthA=(A[4]-'0')*10+(A[5]-'0'); 53 dayA=(A[6]-'0')*10+(A[7]-'0'); 54 yearB=(B[0]-'0')*1000 + (B[1]-'0')*100 + (B[2]-'0')*10 + (B[3]-'0'); 55 monthB=(B[4]-'0')*10 + (B[5]-'0'); 56 dayB=(B[6]-'0')*10 + (B[7]-'0'); 57 58 /*算第一个日期的天数*/ 59 for(i=1;i<yearA;i++) //算这年之前有多少天 60 { 61 day1+=YEAR[i]; 62 } 63 64 for(i=0;i<monthA-1;i++) //算这年这月之前有多少天 65 { 66 if(isleapyear(yearA)) 67 day1+=days[i][1]; //如果是闰年,则加第2组数据 68 else day1+=days[i][0]; //如果不是闰年,加第1组数据 69 } 70 71 day1+=dayA; //算这天是这个月第几天 72 73 /*算第二个日期的天数*/ 74 for(i=1;i<yearB;i++) 75 { 76 day2+=YEAR[i]; 77 } 78 79 for(i=0;i<monthB-1;i++) 80 { 81 if(isleapyear(yearB)) 82 day2+=days[i][1]; 83 else day2+=days[i][0]; 84 } 85 86 day2+=dayB; 87 88 printf("%d\n",absolute(day2-day1)+1); 89 day1=0; 90 day2=0; 91 } 92 return 0; 93 }
日期类的题目,这题的算法是计算两个日期距离0001年1月1日的天数,再相减取绝对值。要细心,变量多,很容易出错。尤其最后要把day1和day2清零,才能进行下一组输入。
题号1043Day of Week
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 int isleapyear(int a) 6 { 7 if ((a%4==0 && a%100!=0) || a%400==0) 8 return 1; 9 else return 0; 10 } 11 12 char days_of_month[12][2]={ 13 {31,31}, 14 {28,29}, 15 {31,31}, 16 {30,30}, 17 {31,31}, 18 {30,30}, 19 {31,31}, 20 {31,31}, 21 {30,30}, 22 {31,31}, 23 {30,30}, 24 {31,31} 25 }; 26 27 char *month_name[12]={ 28 "January", 29 "February", 30 "March", 31 "April", 32 "May", 33 "June", 34 "July", 35 "August", 36 "September", 37 "October", 38 "November", 39 "December" 40 }; 41 42 char *weekday_name[7]={ 43 "Sunday", 44 "Monday", 45 "Tuesday", 46 "Wednesday", 47 "Thursday", 48 "Friday", 49 "Saturday", 50 }; 51 52 //2016.1.1是周五 53 54 int main() 55 { 56 int Y,D; 57 char M[10]; 58 int i,j,YEAR[3000]; 59 int days=0; //算出距离2016.1.1有多少天 60 int weekday; 61 62 for(i=1000;i<3000;i++) //算出每年有多少天(1000~3000年) 63 { 64 if(isleapyear(i)) 65 YEAR[i]=366; 66 else YEAR[i]=365; 67 } 68 69 while(scanf("%d%s%d",&D,M,&Y)!=EOF) 70 { 71 if(Y>=2016) //2016.1.1之后的日期 72 { 73 for(i=2016;i<Y;i++) 74 { 75 days+=YEAR[i]; 76 } 77 for(i=0;i<12;i++) //算这一天是这一年的第几天 78 { 79 if(!strcmp(month_name[i],M)) 80 { 81 if(isleapyear(Y)) 82 { 83 for(j=0;j<i;j++) 84 { 85 days+=days_of_month[j][1]; 86 } 87 continue; 88 } 89 else 90 { 91 for(j=0;j<i;j++) 92 { 93 days+=days_of_month[j][0]; 94 } 95 continue; 96 } 97 } 98 } 99 days+=D; 100 weekday=(days%7+4)%7; //2016.1.1是周五 101 } 102 103 else 104 { 105 for(i=0;i<12;i++) //算这一天是这一年的第几天 106 { 107 if(!strcmp(month_name[i],M)) 108 { 109 if(isleapyear(Y)) 110 { 111 for(j=0;j<i;j++) 112 { 113 days+=days_of_month[j][1]; 114 } 115 } 116 else 117 { 118 for(j=0;j<i;j++) 119 { 120 days+=days_of_month[j][0]; 121 } 122 } 123 } 124 } 125 days+=D; 126 if(isleapyear(Y)) 127 days=366-days+1; 128 else 129 days=365-days+1; 130 for(i=2015;i>Y;i--) 131 { 132 days+=YEAR[i]; 133 } 134 weekday=(5-days%7+7)%7;//思考这个表达式怎么写 135 } 136 137 for(i=0;i<7;i++) 138 { 139 if(weekday==i) 140 { 141 printf("%s\n",weekday_name[i]); 142 continue; 143 } 144 } 145 days=0;//清零,等待下一轮输入 146 } 147 return 0; 148 }
以2016.1.1(周五)为原点,分两部分计算,注意两部分取余计算的公式不同。
题号1070今年的第几天
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 int days[12][2]={ 5 {31,31}, 6 {28,29}, 7 {31,31}, 8 {30,30}, 9 {31,31}, 10 {30,30}, 11 {31,31}, 12 {31,31}, 13 {30,30}, 14 {31,31}, 15 {30,30}, 16 {31,31} 17 }; 18 19 int isleapyear(int a) 20 { 21 if ((a%100!=0 && a%4 == 0) || a%400 == 0) 22 return 1; 23 else return 0; 24 } 25 26 int main() 27 { 28 int i,DAYS=0; 29 int Y,M,D; 30 while(scanf("%d%d%d",&Y,&M,&D)!=EOF) 31 { 32 if(isleapyear(Y)) 33 { 34 for(i=0;i<M-1;i++) 35 { 36 DAYS+=days[i][1]; 37 } 38 } 39 else 40 { 41 for(i=0;i<M-1;i++) 42 { 43 DAYS+=days[i][0]; 44 } 45 } 46 DAYS+=D; 47 printf("%d\n",DAYS); 48 DAYS=0; 49 } 50 return 0; 51 }
做过上面两题,这题就变得简单了。
题号1186打印日期
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 int isleapyear(int a) 5 { 6 if ((a%4==0 && a%100!=0)||a%400==0) 7 return 1; 8 else return 0; 9 } 10 11 int days_of_month[12][2]={ 12 {31,31}, 13 {28,29}, 14 {31,31}, 15 {30,30}, 16 {31,31}, 17 {30,30}, 18 {31,31}, 19 {31,31}, 20 {30,30}, 21 {31,31}, 22 {30,30}, 23 {31,31} 24 }; 25 26 27 int main() 28 { 29 int i; 30 int year,day; 31 while(scanf("%d%d",&year,&day)!=EOF) 32 { 33 if(isleapyear(year)) 34 { 35 for(i=0;i<12;i++) 36 { 37 day-=days_of_month[i][1]; 38 if(day<=0) 39 { 40 day=day+days_of_month[i][1]; 41 break; 42 } 43 } 44 printf("%04d-%02d-%02d\n",year,i+1,day); 45 } 46 else 47 { 48 for(i=0;i<12;i++) 49 { 50 day-=days_of_month[i][0]; 51 if(day<=0) 52 { 53 day=day+days_of_month[i][0]; 54 break; 55 } 56 } 57 printf("%04d-%02d-%02d\n",year,i+1,day); 58 } 59 } 60 return 0; 61 }
这题一开始就想去用笨办法做,用12个if/elseif来解决问题,这样显然过于繁琐。用循环简单,要注意break的条件设置。
再就是输出格式,学会"%04d-%02d-%02d"这个输出方法,不足位数补0。
题号1018统计同成绩学生人数
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 int main() 6 { 7 int N; 8 int *A; 9 int i; 10 int flag; 11 int count=0; 12 while(scanf("%d",&N)!=EOF && N!=0) 13 { 14 A = (int *)malloc(sizeof(int)*N); 15 for(i=0;i<N;i++) 16 { 17 scanf("%d",A+i); 18 } 19 scanf("%d",&flag); 20 for(i=0;i<N;i++) 21 { 22 if(*(A+i)==flag) 23 count++; 24 } 25 printf("%d\n",count); 26 count = 0; 27 } 28 return 0; 29 } 30
题号1431Sort
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 int cmp(const void *a,const void *b) 6 { 7 return *(int *)b-*(int *)a; 8 } 9 10 int main() 11 { 12 int n,m,i; 13 int *A; 14 while(scanf("%d%d",&n,&m)!=EOF) 15 { 16 A = (int *)malloc(sizeof(int)*n); 17 for(i=0;i<n;i++) 18 { 19 scanf("%d",A+i); 20 } 21 qsort(A,n,sizeof(*A),cmp); 22 for(i=0;i<m-1;i++) 23 printf("%d ",*(A+i)); 24 printf("%d\n",*(A+m-1)); 25 } 26 return 0; 27 28 29 } 30
以上两题都没判断输入数的大小,不过也AC了...(懒
题号1156谁是你的潜在朋友
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 6 int main() 7 { 8 int N,M,i,j; 9 int *A; 10 int *count; 11 while(scanf("%d%d",&N,&M)!=EOF) 12 { 13 A = (int *)malloc(sizeof(int)*N); 14 count = (int *)malloc(sizeof(int)*N); 15 for(i=0;i<N;i++) 16 { 17 scanf("%d",A+i); 18 if(*(A+i)>M || *(A+i)>200) 19 break;//如果输入的借书号码不在M范围之内,退出程序? 20 } 21 for(i=0;i<N;i++) 22 { 23 *(count+i)=0;//计数器初始化 24 for(j=0;j<N;j++) 25 { 26 if(*(A+j)==*(A+i)) 27 (*(count+i))++; 28 } 29 (*(count+i))--;//减去和自身的比较 30 if(*(count+i)!=0) 31 printf("%d\n",*(count+i)); 32 else printf("BeiJu\n"); 33 } 34 } 35 return 0; 36 } 37
19行,这个问题还没解决。如何使得输入若不满足需求,直接退出并进行下一组输入?
(2.24注:做剩下的树这个题时,发现遇到了困难,翻书发现这个题包括以上三个题都最好使用Hash方法
核心步骤为:例如统计同成绩的人数,声明一个Hash[101]的数组
for(i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
Hash[x]++;
}
以此来统计哪个分数的人最多。
又例如sort,因为给出的数可能为负数,则把[-500000,500000]区间映射到数组下标[0,1000000]区间,
#define OFFSET 500000
声明数组 Hash[1000001]
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
Hash[x+OFFSET]=1;
}//凡是出现过的数字,改数组元素均被设置为1(初始化为0)
然后从500000开始,遍历数组,从后往前把m个数组元素为1的对应下标输出,也就是前m大个数字。)
题号1088剩下的树
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 int main() 6 { 7 int L,M,i,j; 8 int x,y; 9 int *Hash; 10 int count=0; 11 while(scanf("%d%d",&L,&M)!=EOF && (L>=1 && L<=10000) && (M>=1 && M<=100)) 12 { 13 Hash = (int *)malloc(sizeof(int)*(L+1)); 14 for(i=0;i<L+1;i++) 15 *(Hash+i) = 0;//初始化为全0 16 for(i=0;i<M;i++) 17 { 18 scanf("%d%d",&x,&y); 19 for(j=x;j<=y;j++) 20 *(Hash+j)=1; 21 } //对于每组区间,把数组元素标记为1 22 for(i=0;i<L+1;i++) 23 { 24 if(*(Hash+i)==0) 25 count++; 26 } //计算有多少标为0的元素,表示剩下的树 27 printf("%d\n",count); 28 count = 0; 29 } 30 return 0; 31 }
Hash方法,把移走的区间全标1,最后统计0的个数
题号1065输出梯形
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 int main() 6 { 7 int h; 8 int i,j,k; 9 while(scanf("%d",&h)!=EOF) 10 { 11 for(i=0;i<h;i++)//控制高度,每次循环输出一行 12 { 13 for(j=2*(h-1)-2*i;j>0;j--) 14 { 15 printf(" "); 16 } 17 for(k=h+2*i;k>0;k--) 18 { 19 printf("*"); 20 } 21 printf("\n"); 22 } 23 } 24 return 0; 25 }
题号1432叠筐
题号1161Repeater
题号1052找x
题号1069查找学生信息
(更新中...)