记一下刷题过程和思路,博主是个菜鸟,只有C语言用的顺,如果有不足之处欢迎大家指正。
1001 A+B Format (20分)
Calculate a+b and output the sum in standard format – that is, the digits must be separated into groups of three by commas (unless there are less than four digits).
Input Specification:
Each input file contains one test case. Each case contains a pair of integers a and b where −10^6 ≤a,b≤ 10^6
. The numbers are separated by a space.
Output Specification:
For each test case, you should output the sum of a and b in one line. The sum must be written in the standard format.
思路:这道题由于a,b的范围有限,于是选择一种简单粗暴的做法。
#include <stdio.h>
#include <math.h>
int main()
{
int a,b,c,d[10],i=0;
scanf("%d %d",&a,&b);
c=a+b;
if(c<0)
{
c=-c;
printf("-");
}
if(c>=1000000)printf("%d,%03d,%03d\n",c/1000000, (c/1000)%1000, c%1000);
else if(c>=1000) printf("%d,%03d\n",c/1000, c%1000);
else printf("%d\n",c);
return 0;
}
1002 A+B for Polynomials (25分)
This time, you are supposed to find A+B where A and B are two polynomials.
思路:这道题我按照自己的思路做时,是类似于有序表的合并思路做的,不知道为什么总是通过不了,在网上看到了别人的思路,觉得很好,可以把指数作为数组下标来存储系数,这样不容易出错,还很清晰。
#include <stdio.h>
int main()
{
int k1,k2,m,c=0;
float n,a[1001]={
0};
int i,j;
scanf("%d",&k1);
for(i=0;i<k1;i++)
{
scanf(" %d %f",&m,&n);
a[m]+=n;
}
scanf("%d",&k2);
for(j=0;j<k2;j++)
{
scanf(" %d %f",&m,&n);
a[m]+=n;
}
for(i=1000;i>=0;i--)
{
if(a[i]!=0) c++;
}
printf("%d",c);
for(i=1000;i>=0;i--)
{
if(a[i]!=0)printf(" %d %.1f",i,a[i]);
}
}
1003 Emergency (25分)
As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.
思路:这道题我用迪杰斯特拉算法来做,思路还是挺清晰的,主要是三个循环:初始化、找到k、更新距离。有一个坑是这道题和迪杰斯特拉算法有一点不同是在初始化时起点C1的判断是否走过的flag[C1]不要初始化为1,因为有多条最短路径时还可以经过它。
#include <stdio.h>
#define max 505
#define INF 10000;
typedef struct
{
int t;
}vex;
typedef struct
{
int m[max][max];
int vnum;
int edgenum;
vex v[max];
}graph;
void dijkstra(graph g,int c1,int c2,int n)
{
int i,j,k,min,flag[n],dist[n],prev[n],temp,s[n],tnum[n];//s[i]是从起点到i节点的最短路径条数,tnum[i]是能到达i、节点的队伍总数
for(i=0;i<n;i++)
{
flag[i]=0;
prev[i]=0;
dist[i]=g.m[c1][i];
s[i]=0;
tnum[i]=0;
}
dist[c1]=0;
s[c1]=1;
tnum[c1]=g.v[c1].t;
for(i=0;i<n;i++)
{
k=-1;
min=INF;
for(j=0;j<n;j++)
{
if(flag[j]==0&&dist[j]<min)
{
min=dist[j];
k=j;
}
}
flag[k]=1;
prev[k]=c1;
for(j=0;j<n;j++)
{
temp=dist[k]+g.m[k][j];
if(flag[j]==0&&temp<dist[j])
{
dist[j]=temp;
prev[j]=k;
s[j]=s[k];
tnum[j]=g.v[j].t+tnum[k];
}
else if(flag[j]==0&&temp==dist[j])//有多条最短路径的情况
{
s[j]+=s[k];
tnum[j]=(g.v[j].t+tnum[k]>tnum[j]? g.v[j].t+tnum[k]:tnum[j]);
}
}
}
printf("%d %d",s[c2],tnum[c2]);
}
int main()
{
int n,m,c1,c2;
scanf("%d %d %d %d",&n,&m,&c1,&c2);
graph g;
g.vnum=n;
g.edgenum=m;
int i,j,t1,t2,t3;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
g.m[i][j]=INF;
}
}
for(i=0;i<n;i++)
{
scanf("%d",&g.v[i].t);
}
for(i=0;i<m;i++)
{
scanf("%d %d %d",&t1,&t2,&t3);
g.m[t1][t2]=t3;
g.m[t2][t1]=t3;
}
g.m[c1][c1]=0;
dijkstra(g,c1,c2,n);
return 0;
}
1004 Counting Leaves (30分)
A family hierarchy is usually presented by a pedigree tree. Your job is to count those family members who have no child.
思路:这道题我看网上有人用层级遍历什么的感觉有点想复杂了,其实只要用到树结构的存储就可以了。有一个坑是在输入时不能直接让子节点的层数是父节点的层数+1,因为在没有输入完时可能还不知道父节点的层数,会导致有两个测试点不能通过。只要在输入时记录每个节点的父节点即可,在输入完成后再进行子节点的层数是父节点的层数+1。
#include <stdio.h>
#define max 200
typedef struct
{
int id,level,flag,father;//flag用来判断该节点是否为非叶子节点
}node;
typedef struct
{
node nodes[max];
}tree;
int main()
{
int n,m,i,j,t1,t2,t3,max_level=0,r[max]={
0};
tree t;
scanf("%d %d",&n,&m);
t.nodes[1].level=1;
t.nodes[1].id=1;
t.nodes[1].father=0;
for(i=1;i<=n;i++)
{
t.nodes[i].flag=0;
}
for(i=0;i<m;i++)
{
scanf("%d %d",&t1,&t2);
t.nodes[t1].id=t1;
t.nodes[t1].flag=1;
for(j=0;j<t2;j++)
{
scanf("%d",&t3);
t.nodes[t3].id=t3;
t.nodes[t3].father=t1;
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(t.nodes[j].father==i)
{
t.nodes[j].level=t.nodes[i].level+1;
if(t.nodes[j].level>max_level)max_level=t.nodes[j].level;
}
}
}
for(i=1;i<=n;i++)
{
if(t.nodes[i].flag==0)
{
r[t.nodes[i].level]++;//r[i]用来记录第i层的叶子节点数目
}
}
for(i=1;i<max_level;i++)
{
printf("%d ",r[i]);
}
printf("%d",r[i]);
}
1005 Spell It Right (20分)
Given a non-negative integer N, your task is to compute the sum of all the digits of N, and output every digit of the sum in English.
思路:这道题比较简单,没啥好说的。。。
#include <stdio.h>
#define max 150
int main()
{
char n[max],d[10][10]={
"zero","one","two","three","four","five","six","seven","eight","nine"};
scanf("%s",n);
int i,j,r[max],sum=0;
for(i=0;n[i];i++)
{
sum+=n[i]-'0';
}
if(sum==0)
{
printf("zero");
return 0;
}
for(i=0;sum;i++)
{
r[i]=sum%10;
sum/=10;
}
i--;
for(;i>0;i--)printf("%s ",d[r[i]]);
printf("%s",d[r[i]]);
}
1006 Sign In and Sign Out (25分)
At the beginning of every day, the first person who signs in the computer room will unlock the door, and the last one who signs out will lock the door. Given the records of signing in’s and out’s, you are supposed to find the ones who have unlocked and locked the door on that day.
思路:这道题也比较简单,找出sign in的时间最小的和sign out的时间最大的就行。
#include <stdio.h>
#include <string.h>
#define max 100
typedef struct
{
int h,m,s;
}time;
typedef struct
{
char id[20];
time in,out;
}person;
int main()
{
int i,n;
char min_id[20],max_id[20];
scanf("%d",&n);
time tmin={
24,60,60};
time tmax={
0,0,0};
person p[max];
for(i=0;i<n;i++)
{
scanf("%s %d:%d:%d %d:%d:%d",p[i].id,&p[i].in.h,&p[i].in.m,&p[i].in.s,&p[i].out.h,&p[i].out.m,&p[i].out.s);
if(p[i].in.h<tmin.h || (p[i].in.h==tmin.h&&p[i].in.m<tmin.m) || (p[i].in.h==tmin.h&&p[i].in.m==tmin.m&&p[i].in.s<tmin.s))
{
tmin=p[i].in;
strcpy(min_id,p[i].id);
}
if(p[i].out.h>tmax.h || (p[i].out.h==tmax.h&&p[i].out.m>tmax.m) || (p[i].out.h==tmax.h&&p[i].out.m==tmax.m&&p[i].out.s>tmax.s))
{
tmax=p[i].out;
strcpy(max_id,p[i].id);
}
}
printf("%s %s",min_id,max_id);
return 0;
}
1007 Maximum Subsequence Sum (25分)
思路:s和e分别记录当前子序列的起始点和终止点,t为当前子序列的和。从头开始遍历,若t<0,则舍弃当前子序列,从下一个位置继续寻找。
#include <stdio.h>
int main()
{
int k,n[10001],i,j;
scanf("%d",&k);
for(i=0;i<k;i++)
{
scanf("%d",&n[i]);
}
int t=0,max=-1,s=0,e=k-1,p=0;
for(i=0;i<k;i++)
{
t+=n[i];
if(t<0)
{
t=0;
p=i+1;
}
else if(t>max)
{
max=t;
s=p;
e=i;
}
}
if(max<0)
{
printf("0 %d %d",n[0],n[k-1]);
}
else
{
printf("%d %d %d",max,n[s],n[e]);
}
return 0;
}
1008 Elevator (20分)
The highest building in our city has only one elevator. A request list is made up with N positive numbers. The numbers denote at which floors the elevator will stop, in specified order. It costs 6 seconds to move the elevator up one floor, and 4 seconds to move down one floor. The elevator will stay for 5 seconds at each stop.
For a given request list, you are to compute the total time spent to fulfill the requests on the list. The elevator is on the 0th floor at the beginning and does not have to return to the ground floor when the requests are fulfilled.
思路:这题很简单,理解题意就能做。
#include <stdio.h>
int main()
{
int n,a[110],i,t,s=0;
scanf("%d",&n);
a[0]=0;
for(i=1;i<=n;i++)scanf("%d",&a[i]);
for(i=1;i<=n;i++)
{
t=a[i]-a[i-1];
if(t>0)
{
s+=t*6+5;
}
else
{
s+=(-t)*4+5;
}
}
printf("%d",s);
}
1009 Product of Polynomials (25分)
This time, you are supposed to find A×B where A and B are two polynomials.
思路:和之前的多项式加法思路比较相似,用数组下标记录指数,数组元素记录系数。
#include <stdio.h>
int main()
{
int k1,k2,i,j,t1,maxn=0;
float a[1005]={
0},b[1005]={
0},c[2005]={
0},t2;
scanf("%d",&k1);
for(i=0;i<k1;i++)
{
scanf("%d %f",&t1,&t2);
a[t1]=t2;
}
scanf("%d",&k2);
for(i=0;i<k2;i++)
{
scanf("%d %f",&t1,&t2);
b[t1]=t2;
}
for(i=0;i<1005;i++)
{
for(j=0;j<1005;j++)
{
c[i+j]+=a[i]*b[j];
}
}
for(i=2005;i>=0;i--)
{
if(c[i]!=0.0)maxn++;
}
printf("%d",maxn);
for(i=2005;i>=0;i--)
{
if(c[i]!=0.0)printf(" %d %.1f",i,c[i]);
}
return 0;
}
010 Radix (25分)
Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The answer is yes, if 6 is a decimal number and 110 is a binary number.
Now for any pair of positive integers N1 and N2,your task is to find the radix of one number while that of the other is given.
思路:这道题的坑比较多,我的这个代码目前还有两个测试点没有通过。
1.最大进制数很大,绝对不止36,要用long long int。
2.不能用顺序遍历一个个尝试可能的进制,这样的话会运行超时,需要使用二分法寻找进制。二分法查找进制的下界是未知进制数的最大数字 +1,因为每一位的数字都不能超过进制数,比如十进制的数字就只能是 0-9,不可能会有 abcd。二分法查找进制的上界是已知进制数的数值。
3.当寻找的可能进制有多个的时候,需要找到最小的那个。
#include <stdio.h>
#include <string.h>
#include <math.h>
int main()
{
char n1[600],n2[600],c[600];
long long int radix,e=0,t=0,max_num=0,temp,i,j;
int tag;
scanf("%s %s %d %d",n1,n2,&tag,&radix);
if(tag==2)
{
strcpy(c,n1);
strcpy(n1,n2);
strcpy(n2,c);
}
for(i=0;i<strlen(n2);i++)
{
if('0'<=n2[i]&&n2[i]<='9')
{
temp=(n2[i]-'0');
if(temp>max_num)max_num=temp;
}
else if('a'<=n2[i]&&n2[i]<='z')
{
temp=(n2[i]-'a'+10);
if(temp>max_num)max_num=temp;
}
}
for(i=0;i<strlen(n1);i++)
{
if('0'<=n1[i]&&n1[i]<='9')
{
temp=(n1[i]-'0');
e+=temp*pow(radix,strlen(n1)-1-i);
}
else if('a'<=n1[i]&&n1[i]<='z')
{
temp=(n1[i]-'a'+10);
e+=temp*pow(radix,strlen(n1)-1-i);
}
}
for(j=max_num+1;j<=e;j++)
{
t=0;
for(i=0;i<strlen(n2);i++)
{
if('0'<=n2[i]&&n2[i]<='9')
{
t+=(n2[i]-'0')*pow(j,strlen(n2)-1-i);
}
else if('a'<=n2[i]&&n2[i]<='z')
{
t+=(n2[i]-'a'+10)*pow(j,strlen(n2)-1-i);
}
}
if(t==e)
{
printf("%d",j);
return 0;
}
}
printf("Impossible");
return 0;
}
1011 World Cup Betting (20分)
With the 2010 FIFA World Cup running, football fans the world over were becoming increasingly excited as the best players from the best teams doing battles for the World Cup trophy in South Africa. Similarly, football betting fans were putting their money where their mouths were, by laying all manner of World Cup bets.
思路:这道题比较简单,理解题意后代公式就行。
#include <stdio.h>
int main()
{
float g[3][3],max=0.0,r=1.0;
int i,j,k;
char c[3]={
'W','T','L'};
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
scanf("%f",&g[i][j]);
}
}
for(i=0;i<3;i++)
{
max=0.0;
for(j=0;j<3;j++)
{
if(g[i][j]>max)
{
max=g[i][j];
k=j;
}
}
printf("%c ",c[k]);
r*=g[i][k];
}
printf("%.2f",(r*0.65-1)*2);
return 0;
}