《算法笔记》这本书还是有c语言基础看还是相当轻松的一个过程,但是正如每一种编程语言那样,学习的过程都应该边看边练。这本书好像有配套的习题集(应该有解答),我是没有,只好贴一些自己写的代码,每道题的解答方式都有好几种,多比较,多看。书里有好多编写代码的技巧,阅读一条记一条。
这里按照codeup上的序号编排给出我自己的解决代码,不是太好,供参考。有的没有采用标准输入输出,而是使用了读取文件的方式,仅仅为了方便,提交前注释掉就可以了。部分代码有注释,那应该是我曾经不理解或没有注意到的地方。
问题A:
题目描述
有一个长度为整数L(1<=L<=10000)的马路,可以想象成数轴上长度为L的一个线段,起点是坐标原点,在每个整数坐标点有一棵树,即在0,1,2,...,L共L+1个位置上有L+1棵树。
现在要移走一些树,移走的树的区间用一对数字表示,如 100 200表示移走从100到200之间(包括端点)所有的树。
可能有M(1<=M<=100)个区间,区间之间可能有重叠。现在要求移走所有区间的树之后剩下的树的个数。
输入
两个整数L(1<=L<=10000)和M(1<=M<=100)。
接下来有M组整数,每组有一对数字。
输出
可能有多组输入数据,对于每组输入数据,输出一个数,表示移走所有区间的树之后剩下的树的个数。
样例输入
4 2
1 2
0 2
11 2
1 5
4 7
0 0
样例输出
2
5
#include<cstdio>
int L[100002];
int main(){
int l,m,i;
while(scanf("%d%d",&l,&m)){
if(l==0&&m==0)
break;
L[100002]={1};
for(i=0;i<=l;i++)
L[i]=1;
int a,b;
for(i=0;i<m;i++){
scanf("%d%d",&a,&b);
for(int j=a;j<=b;j++)
if(L[j]==1)
L[j]=0;
}
int num=0;
for(i=0;i<=l;i++)
if(L[i]==1)
num++;
printf("%d\n",num);
}
return 0;
}
问题B:
题目描述
给定两个整数A和B,其表示形式是:从个位开始,每三位数用逗号","隔开。
现在请计算A+B的结果,并以正常形式输出。
输入
输入包含多组数据数据,每组数据占一行,由两个整数A和B组成(-10^9 < A,B < 10^9)。
输出
请计算A+B的结果,并以正常形式输出,每组数据占一行。
#include<cstring>//改成double类型就完蛋了,不知道为什么
int main(){
char a[11],b[11];
while(scanf("%s %s",a,b)!=-1){
int A=0,B=0;
int l1=strlen(a),l2=strlen(b);
int i,m=1;
for(i=l1-1;i>0;i--){
if(a[i]>='0'&&a[i]<='9'){
int d=((a[i]-'0')*m);
A+=d;
m*=10;
}
}
if(a[0]=='-')
A=A*(-1);
else
A=A+(a[0]-'0')*m;
i=0,m=1;
for(i=l2-1;i>0;i--){
if(b[i]>='0'&&b[i]<='9'){
B+=((b[i]-'0')*m);
m*=10;
}
}
if(b[0]=='-')
B=B*(-1);
else
B=B+(b[0]-'0')*m;
int c=A+B;
printf("%d\n",c);
}
return 0;
}
问题C:
题目描述
输入
两个小于1000000000的数
输出
输入可能有多组数据,对于每一组数据,输出Input中的两个数按照题目要求的方法进行运算后得到的结果。
样例输入
24 65
42 66666
3 67
样例输出
66
180
39
#include<cstdio>
#include<cstring>
int main(){
char a[11],b[11];
while(scanf("%s%s",&a,&b)!=-1){
int i,j,sum=0;
for(i=0;i<strlen(a);i++)
for(j=0;j<strlen(b);j++){
sum+=((a[i]-'0')*(b[j]-'0'));
}
printf("%d\n",sum);
}
return 0;
问题D:
题目描述
第一行输入一个数,为n,第二行输入n个数,这n个数中,如果偶数比奇数多,输出NO,否则输出YES。
输入
输入有多组数据。
每组输入n,然后输入n个整数(1<=n<=1000)。
输出
如果偶数比奇数多,输出NO,否则输出YES。
样例输入
1
67
7
0 69 24 78 58 62 64
样例输出
YES
NO
#include<cstdio>
int main(){
int n;
while(scanf("%d",&n)!=-1){
int even,odd,i;
even=odd=0;
for(i=0;i<n;i++){
int num;
scanf("%d",&num);
if(num%2==0)
even++;
else
odd++;
}
if(even>odd)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}
问题E:
题目描述
输入
输出
样例输入
5 1 2 4 14 9
3
1 3
2 5
4 1
样例输出
3
10
7
#include<cstdio>
#include<cstring>
#include<cstdlib>
int main(){
int N,M,a,b,i,temp,reverse,order;
scanf("%d",&N);
int *d=(int*)malloc(sizeof(int)*(N+5));//数组太大很容易超时
d[0]=d[1]=0;
for(i=1;i<=N;i++){
scanf("%d",&temp);
if(i<N)
d[i+1]=d[i]+temp;//最后一个数据无需计(计算i到1的距离)
else
d[0]=temp+d[i]; //总距离
}
scanf("%d",&M);
int *f=(int*)malloc(sizeof(int)*(M+1));
for(i=0;i<M;i++){
scanf("%d%d",&a,&b);
if(a>b){
temp=a;
a=b;
b=temp;
}
order=d[b]-d[a];
reverse=d[0]-order;
if(order<reverse)
f[i]=order;
else
f[i]=reverse;
}
//输出格式
for(i=0;i<M;i++)
printf("%d\n",f[i]);
free(d);
d=NULL;
return 0;
}
问题F:
题目描述
输入
输出
样例输入
4
1 2 3
2 3 4
2147483647 0 2147483646
0 -2147483648 -2147483647
样例输出
Case #1: false
Case #2: true
Case #3: true
Case #4: false
#include<cstdio>
int main(){
//freopen("in.txt","r",stdin);
double a,b,c,d;
int n,i=1;
scanf("%d",&n);
while(n--){
scanf("%lf%lf%lf",&a,&b,&c);
d=a+b;
if(d>c)
printf("Case #%d: true\n",i);
else
printf("Case #%d: false\n",i);
i++;
}
return 0;
}
问题G:
题目描述
给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字:
A1 = 能被5整除的数字中所有偶数的和;A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3-n4...;A3 = 被5除后余2的数字的个数;A4 = 被5除后余3的数字的平均数,精确到小数点后1位;A5 = 被5除后余4的数字中最大数字。输入
输出
对给定的N个正整数,按题目要求计算A1~A5并在一行中顺序输出。数字间以空格分隔,但行末不得有多余空格。
若其中某一类数字不存在,则在相应位置输出“N”。
样例输入
13 1 2 3 4 5 6 7 8 9 10 20 16 18
8 1 2 4 5 6 7 9 16
样例输出
30 11 2 9.7 9
N 11 2 N 9
#include<cstdio>
#include<cmath>
int main(){
freopen("in.txt","r",stdin);
int N;
scanf("%d",&N);
int a1,a2,a3,a4,a5,te,f1,f2,f3,f4,f5;
f1=f2=f3=f4=f5=a1=a2=a3=a4=a5=0;
double a22=1;
for(int i=0;i<N;i++){
scanf("%d",&te);
if(te%5==0&&te%2==0){
a1+=te;
f1=1;}
if(te%5==1){
f2=1;
a22++;
int i=pow(-1.0,a22);
a2+=(te*i);
}
if(te%5==2){
f3=1;
a3++;}
if(te%5==3){
f4++;
a4+=te;}
if(te%5==4){
f5=1;
if(te>a5)
a5=te;
}
}
if(f1)
printf("%d ",a1);
else
printf("N ");
if(f2)
printf("%d ",a2);
else
printf("N ");
if(f3)
printf("%d ",a3);
else
printf("N ");
if(f4)
printf("%.1f ",(1.0*a4)/f4);
else
printf("N ");
if(f5)
printf("%d",a5);
else
printf("N");
return 0;
}
问题H:
题目描述
正整数A的“DA(为1位整数)部分”定义为由A中所有DA组成的新整数PA。例如:给定A = 3862767,DA = 6,则A的“6部分”PA是66,因为A中有2个6。
现给定A、DA、B、DB,请编写程序计算PA + PB。
输入
输出
样例输入
3862767 6 13530293 3
3862767 1 13530293 8
样例输出
399
0
#include<cstdio>
#include<cstring>
int main(){
freopen("in.txt","r",stdin);
char A[10],B[10],DA,DB;
scanf("%s %c%s %c",&A,&DA,&B,&DB);
int PA,PB,i,j=1;
PA=PB=0;
for(i=0;i<strlen(A);i++)
if(A[i]==DA){
PA=PA+(DA-'0')*j;
j*=10;
}
j=1;
for(i=0;i<strlen(B);i++){
if(B[i]==DB){
PB=PB+(DB-'0')*j;
j*=10;
}
}
printf("%d",PA+PB);
return 0;
}
问题I:
题目描述
大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示:
现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。
输入
输出
样例输入
10
C J
J B
C B
B B
B C
C C
C B
J B
B C
J J
样例输出
5 3 2
2 3 5
B B
#include<cstdio>
#include<map>
int main(){
freopen("in.txt","r",stdin);
int N;
scanf("%d",&N);
int v1,v2,a1,a2,l1,l2;
v1=v2=a1=a2=l1=l2=0;
std::map<char,int> PA,PB;
char a,b;
for(int i=0;i<N;i++){
getchar();//这一步不可少,否则无法读入数据
scanf("%c %c",&a,&b);
if(a=='C'&&b=='J'){
v1++;
l2++;
PA['C']++;
}
if(a=='C'&&b=='B'){
l1++;
v2++;
PB['B']++;
}
if(a=='J'&&b=='B'){
v1++;
l2++;
PA['J']++;
}
if(a=='J'&&b=='C'){
l1++;
v2++;
PB['C']++;
}
if(a=='B'&&b=='C'){
v1++;
l2++;
PA['B']++;
}
if(a=='B'&&b=='J'){
l1++;
v2++;
PB['J']++;
}
if(a==b){
a1++;
a2++;
}
}
printf("%d %d %d\n",v1,a1,l1);
printf("%d %d %d\n",v2,a2,l2);
char PAA='B',PBB='B';
if(PA['C']>PA[PAA])
PAA='C';
if(PA['J']>PA[PAA])
PAA='J';
if(PB['C']>PB[PBB])
PBB='C';
if(PB['J']>PB[PBB])
PBB='J';
printf("%c %c\n",PAA,PBB);
return 0;
}