点击可展开上面目录
Acm.njupt 1001-1026简单题
第一页许多是简单题,每题拿出来说说,没有必要,也说不了什么.
直接贴上AC的代码.初学者一题题做,看看别人的AC代码,寻找自己的问题.
记得实习公司的经理说过,最快提高编码水平的方法有一个就是看别人的代码.简单题没有太多需要解释的方法,就是训练一些编码方法.
由于第一页的许多题目都是大二的时候写的,许多代码不简洁,算法太水,低级错误等等应该都有.不管怎样,还是AC了.
贴出来,有问题大家指出,太菜的地方各位谅解.
描述
给定两个整数,求它们之和。
输入
两个整数A,B.
输出
两个整数的和。
样例输入
1 2
样例输出
3
小结 : 代码不贴了,看到AC代码中有0内存的方法,上网搜,有人说是用汇编封装,有人说是内存泄露,或者oj系统bug.不得而知,求知情者指教.
描述
给定N个整数(1<=N<=100),求出这N个数中的最大值,最小值。
输入
多组数据,第一行为一个整数N,第二行为N个不超过100的正整数,用空格隔开。
输出
对每组数据输出一行,包含两个整数,用一个空格隔开,分别表示N个数中的最大值和最小值
样例输入
5
4 6 7 3 1
4
4 3 5 1
样例输出
7 1
5 1
#include <cstdio> const int N = 101; int main() { int a[N]; int n,i,max,min; while(scanf("%d",&n)!=EOF) { max = -1,min = 101; for(i=1;i<=n;i++) { scanf("%d",&a[i]); if(a[i]>max) max = a[i]; if(a[i]<min) min = a[i]; } printf("%d %d\n",max,min); } return 0; }
小结 : 这题测试不是很难,故最简单的遍历能够AC,比较2*N次.还有更简化的方法就是,相邻的两两比较,再用小的跟min比较,大的跟max比较,比较次数为1.5*N次.
改进后代码如下:
#include <iostream> using namespace std; const int N = 101; #define INF 99999 void swap(int &a,int &b) { a=a^b; b=a^b; a=a^b; } int main() { int A[N]; int n,i,max,min; while(scanf("%d",&n)!=EOF) { max = -1,min = INF; for(i=0; i<n; i++) { scanf("%d",&A[i]); } for(int i=0; i<n-1; i+=2) { if(A[i]>A[i+1]) swap(A[i],A[i+1]); if(A[i]<min) min=A[i]; if(A[i+1]>max) max=A[i+1]; } if(A[n-1]<min) min=A[n-1]; if(A[n-1]>max) max=A[n-1]; printf("%d %d\n",max,min); } return 0; }
描述
在数学上,斐波那契数列(FibonacciSequence),是以递归的方法来定义:
F0 = 0
F1 = 1
Fn = Fn - 1 + Fn - 2
用文字来说,就是斐波那契数列由0和1开始,之后的斐波那契数就由之前的两数相加。首几个斐波那契数是:
0, 1, 1, 2, 3, 5,8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946,………………
特别指出:0不是第一项,而是第零项。
在西方,最先研究这个数列的人是比萨的列奥纳多(又名斐波那契),他描述兔子生长的数目时用上了这数列。
第一个月有一对刚诞生的兔子
第两个月之后它们可以生育
每月每对可生育的兔子会诞生下一对新兔子
兔子永不死去
假设在n月有新生及可生育的兔子总共a对,n+1月就总共有b对。在n+2月必定总共有a+b对:因为在n+2月的时候,所有在n月就已存在的a对兔子皆已可以生育并诞下a对后代;同时在前一月(n+1月)之b对兔子中,在当月属于新诞生的兔子尚不能生育。
现请以较短的时间,求出斐波那契数列第n项数值,0≤n≤40。
#include <iostream> using namespace std; int fib[46],j=2,i; int main() { fib[0]=0; fib[1]=1; while(j<=42) { fib[j]=fib[j-1]+fib[j-2]; j++; } while(scanf("%d",&i)!=EOF) { printf("%d\n",fib[i]); } return 0; }
描述
线性表是n个元素的有序集合(n0),n是线性表中元素的个数,称为线性表的长度。可以用一组地址连续的存储单元依次存储线性表中元素,采用这种存储方式的线性表称为顺序表。
请在顺序表上实现运算,实现顺序表的逆置,删除表中所有元素值等于x的元素。
输入
三组数据,顺序表元素类型分别为整型、字符型和实型。
每一组第一行给出元素数目n(0<n≤1000),第二行给出元素数值,第三行给出待删除的元素。
输出
三组数据,每一组第一行为逆置后的顺序表元素,第二行是在此基础上删除指定元素后的顺序表元素
样例输入
8
1 2 3 7 5 6 7 8
7
3
a c m
h
4
1.2 3.4 5.6 7.8
1.2
样例输出
8 7 6 5 7 3 2 1
8 6 5 3 2 1
m c a
m c a
7.8 5.6 3.4 1.2
7.8 5.6 3.4
#include<iostream> #include<math.h> using namespace std; #define EPS 1e-6 struct list { int ele; char ele2; float ele3; int cur; }; int main() { int n,p,i,a,p2,len; float b; struct list str[1002]; scanf("%d",&n); len=n; p=0; str[0].cur=-1; for(i=1;i<=n;i++) { scanf("%d",&str[i].ele); str[i].cur=str[p].cur; str[p].cur=i; } p=str[0].cur; while(p!=-1) { cout<<str[p].ele<<' '; p=str[p].cur; } cout<<endl; scanf("%d",&a); p2=0; p=str[p2].cur; while(p!=-1) { if(str[p].ele==a) { str[p2].cur=str[p].cur; p=str[p2].cur; len--; } else { p2=p; p=str[p].cur; } } if(len<=0) { cout<<endl; } else { p=str[0].cur; while(p!=-1) { cout<<str[p].ele<<' '; p=str[p].cur; } cout<<endl; } getchar(); scanf("%d",&n); len=n; p=0; str[0].cur=-1; getchar(); for(i=1;i<=n;i++) { scanf("%c",&str[i].ele2); str[i].cur=str[p].cur; str[p].cur=i; getchar(); } p=str[0].cur; while(p!=-1) { cout<<str[p].ele2<<' '; p=str[p].cur; } cout<<endl; scanf("%c",&a); p2=0; p=str[p2].cur; while(p!=-1) { if(str[p].ele2==a) { str[p2].cur=str[p].cur; p=str[p2].cur; len--; } else { p2=p; p=str[p].cur; } } if(len==0) cout<<endl; else { p=str[0].cur; while(p!=-1) { cout<<str[p].ele2<<' '; p=str[p].cur; } cout<<endl; } scanf("%d",&n); len=n; p=0; str[0].cur=-1; for(i=1;i<=n;i++) { scanf("%f",&str[i].ele3); str[i].cur=str[p].cur; str[p].cur=i; } p=str[0].cur; while(p!=-1) { cout<<str[p].ele3<<' '; p=str[p].cur; } cout<<endl; scanf("%f",&b); p2=0; p=str[p2].cur; while(p!=-1) { if(fabs(str[p].ele3-b)<=EPS) { str[p2].cur=str[p].cur; p=str[p2].cur; len--; } else { p2=p; p=str[p].cur; } } if(len<=0) cout<<endl; else { p=str[0].cur; while(p!=-1) { cout<<str[p].ele3<<' '; p=str[p].cur; } cout<<endl; } return 0; }
小结 : 这题的代码用链表写的,写的非常屎,大家不要学习
小结 : 当时没AC,有空再做.
描述
a3 = b3 + c3 + d3为完美立方等式。例如123 = 63 + 83 + 103 。编写一个程序,对任给的正整数N (N≤100),寻找所有的四元组(a, b, c, d),使得a3 = b3 + c3 + d3,其中1<a,b, c, d ≤N。
输入
正整数N (N≤100)
输出
每行输出一个完美立方,按照a的值,从小到大依次输出。当两个完美立方等式中a的值相同,则依次按照b、c、d进行非降升序排列输出,即b值小的先输出、然后c值小的先输出、然后d值小的先输出。
样例输入
24
样例输出
Cube = 6, Triple = (3,4,5)
Cube = 12, Triple = (6,8,10)
Cube = 18, Triple = (2,12,16)
Cube = 18, Triple = (9,12,15)
Cube = 19, Triple = (3,10,18)
Cube = 20, Triple = (7,14,17)
Cube = 24, Triple = (12,16,20)
#include<iostream> using namespace std; struct node { int a; int b; int c; int d; }; int main() { int i,j,k,m,n=0; struct node str[100]; for(i=6;i<=100;i++) { for(j=2;j<=i;j++) { for(k=j;k<=i;k++) { for(m=k;m<=i;m++) { if(i*i*i==(j*j*j+k*k*k+m*m*m)) { str[n].a=i; str[n].b=j; str[n].c=k; str[n].d=m; n++; } } } } } while(scanf("%d",&j)!=EOF) { for(i=0;;i++) { if(str[i].a>j||i>=n) break; cout<<"Cube = "<<str[i].a<<", Triple = ("<<str[i].b<<","<<str[i].c<<","<<str[i].d<<")"<<endl; } } return 0; }
小结 : 大家代码可以跟简化很多.
描述
在我们现在使用的日历中, 闰年被定义为能被4整除的年份,但是能被100整除而不能被400整除的年是例外,它们不是闰年。例如:1700, 1800, 1900 和 2100 不是闰年,而 1600, 2000 和 2400是闰年。
给定公元2000年1月1日后的某年某月某日(包括2000年1月1日),你的任务:(1)给出这一天从公元2000年1月1日开始逝去的天数,(2)判断这一天是当年的第几天。
输入
输入包含若干行,每行包含三个空格间隔的正整数,它们分别表示年、月、日。输入最后一行是−1, 不必处理。可以假设结果的年份不会超过9999。
输出
多组,每组两行,分别为每行输入所代表的一天从公元2000年1月1日开始逝去的天数、在当年的第几天。
样例输入
2000 1 1
2009 3 14
-1
样例输出
0
1
3360
73
#include<iostream> using namespace std; bool f(int a) { if(a%4==0&&!(a%100==0&&a%400!=0)) return true; else return false; } int main() { int num,k,yu,ni,ri,i,num1; int Ryue[12]={31,29,31,30,31,30,31,31,30,31,30,31}; int yue[12]={31,28,31,30,31,30,31,31,30,31,30,31}; while(scanf("%d%d%d",&ni,&yu,&ri)!=EOF) { num=0; if(ni==-1) break; k=2000; while(k<ni) { if(f(k)) num+=366; else num+=365; k++; } num1=num; i=0; k=yu; for(i=0;i<k-1;i++) { if(f(ni)) num+=Ryue[i]; else num+=yue[i]; } num+=ri; cout<<num-1<<endl<<num-num1<<endl; } return 0; }
描述
编程精确计算2的N次方。(N是介于100和1000之间的整数)。
输入
正整数N (100≤N≤1000)
输出
2的N次方
样例输入
200
样例输出
1606938044258990275541962092341162602522202993782792835301376
#include<iostream> using namespace std; int main() { int str[1000],len,n,i,b,temp; while(scanf("%d",&n)!=EOF) { str[0]=1; len=1; while(n--) { b=0; for(i=0;i<len;i++) { temp=str[i]*2+b; b=temp/10; str[i]=temp%10; } while(b!=0) { str[i]=b%10; b=b/10; i++; len++; } } for(i=len-1;i>=0;i--) cout<<str[i]; cout<<endl; } return 0; }
描述
要求找出具有下列性质数的个数(包含输入的自然数n):
先输入一个自然数n(n<=1000),然后对此自然数按照如下方法进行处理:
1. 不作任何处理;
2. 在它的左边加上一个自然数,但该自然数不能超过原数的一半;
3. 加上数后,继续按此规则进行处理,直到不能再加自然数为止.
输入
一个自然数n
输出
一个数,表示满足条件的数的个数
样例输入
6
样例输出
6
提示
样例说明:满足条件的数是6,16,26,126,36,136
#include<iostream> #include<math.h> using namespace std; __int64 f[1001]; int main() { __int64 i,j,n; memset(f,0,sizeof(f)); //freopen("aa.txt","r",stdin); f[0]=1; f[1]=1; f[2]=2; f[3]=2; for(i=4;i<1001;i++) { for(j=0;j<=i/2;j++) { f[i]+=f[j]; } } while(scanf("%d",&n)!=EOF) { printf("%I64d\n",f[n]); } return 0; }
描述
求两个非负整数(1000位以内)的和。
输入
两个非负整数(1000位以内),以空格分隔。
输出
两个非负整数的和。
样例输入
111111111111 222222222222
样例输出
333333333333
#include<iostream> using namespace std; #define maxn 1001 void swap(char &a,char &b) { a=a^b; b=a^b; a=a^b; } void f(char *s1,char *s2) { int i,temp; int n1=strlen(s1); int n2=strlen(s2); char t[maxn]; if(n1<n2) { strcpy(t,s1); strcpy(s1,s2); strcpy(s2,t); swap(n1,n2); } int b=0; for(i=0; i<n1-i-1; i++) { swap(s1[i],s1[n1-i-1]); } for(i=0; i<n2-i-1; i++) { swap(s2[i],s2[n2-i-1]); } for(i=n2; i<n1; i++) { s2[i]='0'; } for(i=0; i<n1; i++) { temp=(s1[i]-'0')+(s2[i]-'0')+b; b=temp/10; s1[i]=temp%10+'0'; } while(b!=0) { temp=b; b=b/10; s1[i]=temp%10+'0'; i++; } int n=i; for(i=0; i<n-i-1; i++) { swap(s1[i],s1[n-i-1]); } s1[n]='\0'; } int main() { char s1[maxn],s2[maxn]; while(scanf("%s%s",&s1,&s2)!=EOF) { f(s1,s2); cout<<s1<<endl; } return 0; }
小结 : 还是很屎的代码.
描述
将一个十进制数N转换成R进制数输出,2≤R≤16,R≠10。
输入
多行。第一行指出以下一共有多少组数据,后续每行包含两个整数N和R,以空格分隔,-100000≤N≤100000,2≤R≤16,R≠10。
输出
多行。每行给出转换后的R进制数。
样例输入
3
7 2
23 12
-4 3
样例输出
111
1B
-11
#include<iostream> using namespace std; int f(int n,int r,int s[]) { int temp; int i=0; do { s[i]=n%r; n=n/r; i++; }while(n!=0); n=i; for(i=0;i<n-i;i++) { temp=s[i]; s[i]=s[n-i-1]; s[n-i-1]=temp; } return n; } int main() { int t,n,r,i; int s[200001]; bool flag; char str[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; scanf("%d",&t); while(t--) { flag=false; scanf("%d%d",&n,&r); if(n<0) { flag=true; n=-n; } n=f(n,r,s); if(flag) cout<<"-"; for(i=0;i<n;i++) { cout<<str[s[i]]; } cout<<endl; } return 0; }
描述
给定三条边的长度,判断能否组成三角形,如果可以,判断三角形的形状。
输入
一组数据,每行三个实数,在(0,10]之间,精确到小数点后第四位。最后以0 0 0表示结束。
输出
根据每行的数据判断,如果不能组成三角形,则输出“Not a triangle”;如果是“等腰三角形”,则输出“Isosceles triangle”;如果是“直角三角形”,则输出“Righttriangle”;如果是“等腰直角三角形”,则输出“Isosceles right triangle”;如果是“等边三角形”,则输出“Equilateral triangle”;否则,输出“General triangle”。最后输出一行“End”。
样例输入
1.4142 1.4142 2
1.0000 4.0000 5.0000
0 0 0
样例输出
Isosceles right triangle
Not a triangle
End
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; int Isosceles(double a,double b,double c); int Right(double a,double b,double c); int istriangle(double a,double b,double c) { if(a<1e-3) return 0; if(a+b-c>1e-3) return 1; return 0; } int Equilateral(double a,double b,double c) { if(fabs(a-c)<1e-3) return 1; return 0; } int IsRight(double a,double b,double c) { double aa=pow(a*1.0,2),bb=pow(b*1.0,2),cc=pow(c*1.0,2); if(fabs(aa+bb-cc)<1e-3&&(fabs(a-b)<1e-3)) return 1; return 0; } int Right(double a,double b,double c) { if(!(fabs(a-b)<1e-3)) { double aa=pow(a*1.0,2),bb=pow(b*1.0,2),cc=pow(c*1.0,2); if(fabs(aa+bb-cc)<1e-3) return 1; } return 0; } int Isosceles(double a,double b,double c) { if(fabs(a-b)<1e-3||fabs(c-b)<1e-3) return 1; return 0; } int main() { double temp[5]; int sum; while(1) { scanf("%lf%lf%lf",&temp[0],&temp[1],&temp[2]); if(temp[0]==0) break; sum=0; //sort sort(temp,temp+3); if(istriangle(temp[0],temp[1],temp[2])==0) printf("Not a triangle\n"); else { if(Equilateral(temp[0],temp[1],temp[2])==1) { sum++; printf("Equilateral triangle\n"); } else { if(IsRight(temp[0],temp[1],temp[2])==1) { sum++; printf("Isosceles right triangle\n"); } else { if(Isosceles(temp[0],temp[1],temp[2])==1) { sum++; printf("Isosceles triangle\n"); } else { if(Right(temp[0],temp[1],temp[2])==1) { sum++; printf("Right triangle\n"); } } } } if(sum==0) { printf("General triangle\n"); } } } printf("End"); return 0; }
小结 : 精确到小数点后四位,判断时要用1E-3.当时-3,-4,-5都试过,-3 AC了.
描述
在一组数据(数目不超过10000)中,插入新数,删除所有与给定数相等的数据。
输入
第一行是未排序的一组非负整数,数目不超过10000。以-1作为结束标志。
第二行是要插入的数。
第三行是要删除的数。
输出
第一行输出自小到大排好序的数。如果没有元素,输出“No elements.”(不包括引号)。
第二行输出插入后自小到大排好序的数,以“,”隔开。
第三行输出删除后自小到大排好序的数,以“,”隔开。如果没有元素,输出“No elements.”(不包括引号)。
样例输入
100 98 79 63 44 99 -1
88
79
样例输出
44,63,79,98,99,100
44,63,79,88,98,99,100
44,63,88,98,99,100
#include<iostream> using namespace std; int main() { int m=0,i,j,jia,jian,temp,str[10001]; while(cin>>str[m]&&str[m]!=-1) {m++;} cin>>jia>>jian; str[m]=jia; for(j=m-2;j>=0;j--) { for(i=0;i<=j;i++) { if(str[i]>str[i+1]) { temp=str[i]; str[i]=str[i+1]; str[i+1]=temp; } } } if(m==0) cout<<"No elements."<<endl; else{ for(i=0;i<=m-2;i++) { cout<<str[i]<<','; } cout<<str[m-1]<<endl; } for(j=m-1;j>=0;j--) { for(i=0;i<=j;i++) { if(str[i]>str[i+1]) { temp=str[i]; str[i]=str[i+1]; str[i+1]=temp; } } } for(i=0;i<=m-1;i++) { cout<<str[i]<<','; } cout<<str[m]<<endl; for(i=0;i<=m;i++) { if(str[i]==jian) { for(j=i;j<=m-1;j++) { str[j]=str[j+1]; } m=m-1; i=i-1; } } if(m==-1) { cout<<"No elements."<<endl; } else if(m==0) { cout<<str[m]<<endl; } else{ for(i=0;i<=m-1;i++) { cout<<str[i]<<','; } cout<<str[m]<<endl;} return 0; }
描述
求两个正整数的最大公约数和最小公倍数
输入
两个正整数A,B
输出
两个正整数的最大公约数、最小公倍数
样例输入
4 3
样例输出
1 12
#include<iostream> using namespace std; void f(int &a,int &b) { if(a<b) a=a^b; b=a^b; a=a^b; } int f1(int a,int b) { int temp; int A=a,B=b; F(A,B); while(A!=B) { temp=A-B; A=temp; f(A,B); } return A; } int main() { int a,b; while(scanf("%d%d",&a,&b)!=EOF) { cout<<f1(a,b)<<' '<<a*b/f1(a,b)<<endl; } return 0; }
小结 : 进一步分析见blog:
描述
求R的n次幂(0.0<r<99.999,0<n<=25)
输入
每行输入两个数R和n
R值占1-6列,n占8-9列
输出
对应于每一行输入,输出R的n次幂
前导的0不要输出
无意义的0不要输出
如果结果是一个整数,不要输出小数点
最后一行是空行
样例输入
95.123 12
0.4321 20
5.1234 15
6.7592 9
98.999 10
1.0100 12
样例输出
548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201
import java.io.*; import java.util.*; import java.math.*; public class Main { public static void main(String args[]){ Scanner cin = new Scanner(System.in); Integer n; BigDecimal a; String s; while(cin.hasNext()){ a = cin.nextBigDecimal(); n = cin.nextInt(); s = a.pow(n).stripTrailingZeros().toPlainString(); if(s.charAt(0) == '0') s = s.substring(1); System.out.println(s); } } }
小结 : 投机取巧,java封装了大数计算,~~~
描述
今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样一道题目:
设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。
同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:
有一个数字串:312, 当N=3,K=1时会有以下两种分法:
1) 3*12=36
2) 31*2=62
这时,符合题目要求的结果是:31*2=62
现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。
输入
输入共有两行:
第一行共有2个自然数N,K(6≤N≤40,1≤K≤6)
第二行是一个长度为N的数字串。
输出
输出所求得的最大乘积(一个自然数),答案在long long 数据范围之内。
#include<iostream> #define MAX 50 using namespace std; __int64 max(__int64 a,__int64 b) { return a>=b?a:b; } __int64 G[MAX][MAX],dp[MAX][8],str[MAX]; int main() { __int64 n,m,i,j,l; char ch; while(scanf("%I64d%I64d",&n,&m)!=EOF) { getchar(); for(i=1;i<=n;i++) { scanf("%c",&ch); str[i]=ch-'0'; G[i][i]=str[i]; } for(i=1;i<=n-1;i++) { for(j=i+1;j<=n;j++) { G[i][j]=G[i][j-1]*10+str[j]; } } for(i=1;i<=n;i++) dp[i][0]=G[1][i]; for(i=1;i<=n;i++) { for(j=1;j<=i;j++) { dp[i][j]=0; for(l=j;l<i;l++) { dp[i][j]=max(dp[i][j],dp[l][j-1]*G[l+1][i]); } } } printf("%I64d\n",dp[n][m]); } return 0; }
小结 : 动态规划问题.
描述
二叉树(binary tree)是非常重要的树形数据结构,它是结点的有限集合,该集合或者为空集,或者是由一个根和两个互不相交的、称为该根的左子树和右子树的二叉树组成。
一般意义上,遍历(traverse)一棵二叉树意味着对该二叉树中的每个结点访问且仅访问一次。
(1)若二叉树不为空,先序遍历是指先访问该树根结点,再访问先序遍历左子树,最后先序遍历右子树。
(2)若二叉树不为空,中序遍历是指先中序遍历左子树,再访问该树根结点,最后中序遍历右子树。
(3)若二叉树不为空,后序遍历是指先后序遍历左子树,再后序遍历右子树,最后访问该树根结点。
图1018-1给出一棵二叉树,先序遍历序列为A BD C E F,中序遍历序列为B D A E C F,后序遍历序列为D B E F C A,样例输出给出了输出格式。
图1018-1
编程建立下图1018-2描述的二叉树,给出先序、中序和后序遍历序列。
图1018-2
输入
无需显式输入任何数据
输出
共三行,依次输出先序、中序和后序遍历序列。
#include<stdio.h> int main() { printf("PreOrder: D E H F J G C K A B\nInOrder: H E J F G K C D A B\nPostOrder: H J K C G F E B A D\n"); return 0; }
小结 : 都说了没有显示输入~~
二叉树是非常重要的树形数据结构,根据该树的先序、中序或后序遍历序列可以建立一棵二叉树。例如输入先序遍历序列A B # D # # C E # # F # #可以建立图1019-1所示的二叉树,这里用#代表空树或空子树(另一种说法:若无孩子结点,则用#代替),如图1019-2。
图1019-1
图1019-2
请实现基于遍历的二叉树运算:求高度、计算结点数目
输入
二叉树的先序遍历序列,用#代表空树或空子树。
输出
共五行
前三行依次输出先序、中序和后序遍历序列,
第四行输出二叉树的高度,
第五行依次输出二叉树总结点数目、叶子结点数目、度为1的结点数目。
#include<iostream> using namespace std; struct BTnode { char n; struct BTnode *l; struct BTnode *r; }; void f(struct BTnode * &t) { char c; cin>>c; if(c=='#') t=NULL; else{ t=new struct BTnode; t->n=c; f(t->l); f(t->r); } } void f1(struct BTnode *t) { if(t) { cout<<' '<<t->n; f1(t->l); f1(t->r); } } void f2(struct BTnode *t) { if(t) { f2(t->l); cout<<' '<<t->n; f2(t->r); } } void f3(struct BTnode *t) { if(t) { f3(t->l); f3(t->r); cout<<' '<<t->n; } } int f4(struct BTnode *t)//?????????????????????????????? { if(t==NULL) return 0; int lhigh=f4(t->l); int rhigh=f4(t->r); if(lhigh>=rhigh) return lhigh+1; else return rhigh+1; } void f5(struct BTnode *t,int &flag) { if(t) { if(!t->l&&!t->r) flag++; f5(t->l,flag); f5(t->r,flag); } } void f6(struct BTnode *t,int &flag1) { if(t) { flag1++; f6(t->l,flag1); f6(t->r,flag1); } } void f7(struct BTnode *t,int &flag2) { if(t) { if((!(t->r))&&t->l) { flag2++; f7(t->l,flag2); } if((!(t->l))&&t->r) { flag2++; f7(t->r,flag2); } if(t->r&&t->l) { f7(t->l,flag2); f7(t->r,flag2); } } } int main() { int flag=0; int flag1=0; int flag2=0; struct BTnode *first; f(first); cout<<"PreOrder:"; f1(first); cout<<endl; cout<<"InOrder:"; f2(first); cout<<endl; cout<<"PostOrder:"; f3(first); cout<<endl; cout<<f4(first)<<endl; f6(first,flag1); cout<<flag1<<' '; f5(first,flag); cout<<flag<<' '; f7(first,flag2); cout<<flag2<<endl; return 0; }
描述
二叉树是非常重要的树形数据结构,层次遍历一棵二叉树是按从上到下、从左到右的次序访问树上的结点。例如,图1020所示的二叉树层次遍历序列为A B C D E F。
图1020
请根据先序遍历序列建立一棵的二叉树(用#代表空树或空子树),输出层次遍历序列。
输入
二叉树的先序遍历序列,用#代表空树或空子树
输出
二叉树层次遍历序列
样例输入
A B # D # # C E # # F # #
样例输出
LevelOrder: A B C D E F
#include<iostream> #include<deque> #include<math.h> #include<string> using namespace std; struct node { char A; struct node * r; struct node * l; }; deque <struct node *> S; struct node *build() { char ch; cin>>ch; struct node *first; first=new struct node; if(ch=='#') first=NULL; else { first->A=ch; first->l=build(); first->r=build(); } return first; } void f(struct node *first) { if(first) S.push_back(first); while(S.size()>0) { struct node *p=S.front(); S.pop_front(); cout<<' '<<p->A; if(p->l) S.push_back(p->l); if(p->r) S.push_back(p->r); } return ; } int f(const void *a,const void *b) { return 1; } int main() { struct node *first; //freopen("aa.txt","r",stdin); first=build(); cout<<"LevelOrder:"; f(first); cout<<endl; return 0; }
描述
二叉树是非常重要的树形数据结构。复制一棵二叉树是在另一个存储区存放相同的结构和内容,而一棵二叉树上所有左右子树互换是在原存储区上的运算。
请分别根据先序遍历序列建立两棵的二叉树(用#代表空树或空子树),再将这两棵二叉树复制为左右子树建立第三棵二叉树,输出先序和层次遍历序列,最后将第三棵二叉树上所有左右子树互换,并输出先序和层次遍历序列。
输入
共三行
前两行分别对应两棵二叉树的先序遍历序列,用#代表空树或空子树
第三行为第三棵二叉树的根结点。
输出
共四行
前两行为第三棵二叉树生成时的先序、层次遍历序列,
后两行为第三棵二叉树左右子树互换后的先序、层次遍历序列。
样例输入
B # D # #
C E # # F # #
A
样例输出
PreOrder: A B D C E F
LevelOrder: A B C D E F
PreOrder: A C F E B D
LevelOrder: A C B F E D
#include<iostream> #include<deque> using namespace std; struct node { char c; struct node *ld; struct node *rd; }; deque <struct node *> S; struct node *build() { char ch; cin>>ch; struct node *p; p=(struct node *)malloc(1*sizeof(struct node)); if(ch=='#') { p=NULL; } else { p->c=ch; p->ld=build(); p->rd=build(); } return p; } void f(struct node *p) { if(p) { cout<<' '<<p->c; } if(p->ld) { f(p->ld); } if(p->rd) { f(p->rd); } return ; } void f2(struct node *first) { struct node *temp; if(first) { temp=first->ld; first->ld=first->rd; first->rd=temp; } if(first->ld) { f2(first->ld); } if(first->rd) { f2(first->rd); } return ; } void f3(struct node *first) { if(first) S.push_back(first); while(S.size()>0) { struct node *p=S.front(); S.pop_front(); cout<<' '<<p->c; if(p->ld) S.push_back(p->ld); if(p->rd) S.push_back(p->rd); } return ; } struct node *str[4]; int main() { //freopen("fuck.txt","r",stdin); int i; char ch; for(i=1;i<=2;i++) { str[i]=build(); } cin>>ch; str[3]=new struct node; str[3]->c=ch; str[3]->ld=str[1]; str[3]->rd=str[2]; cout<<"PreOrder:"; f(str[3]); cout<<endl; cout<<"LevelOrder:"; f3(str[3]); cout<<endl; f2(str[3]); cout<<"PreOrder:"; f(str[3]); cout<<endl; cout<<"LevelOrder:"; f3(str[3]); cout<<endl; return 0; }
描述
已知电文包括的字符集为{A,C,I,M,N,P,T,U},输入对应权值,对字符集合进行哈夫曼编码,完成电文的哈夫曼编码与译码工作。
输入
共三行:第一行为对应字符集{A,C,I,M,N,P,T,U}的权值第二行为一段字符串表示的电文(长度不超过1000);第三行为一段电文的哈夫曼编码。
输出
共十行:
前八行为各字符的编码;
第九行是与第二行输入对应的哈夫曼编码;
第十行是与第三行输入对应的电文。
样例输入
1 2 3 4 5 6 7 8
NUPTICPCACM
1111011111100
样例输出
A: 11110
C: 11111
I: 1110
M: 100
N: 101
P: 110
T: 00
U: 01
1010111000111011111110111111111011111100
ACM
#include<iostream> #include<queue> #include<string> using namespace std; #define MAX 10 char str[8]={'A','C','I','M','N','P','T','U'}; int temp[MAX*3]; int str2[256][MAX*3]; string str3; class node { public: int k; char c; node *l,*r; node() { c='0'; k=0;r=l=NULL; } node(int a,char s) { k=a;r=l=NULL; c=s; } friend node* uni(node *p,node *q) { node *temp=new node(p->k+q->k,'0'); temp->l=p; temp->r=q; return temp; } friend void prim(node *p,int L); }; void prim(node *p,int L) { if(!p->r) { str2[p->c][0]=L; for(int i=1;i<=L;i++) { str2[p->c][i]=temp[i-1]; } } else { temp[L]=0; prim(p->l,L+1); temp[L]=1; prim(p->r,L+1); } } class nodeCmp : public binary_function<node*, node*, bool> { public: bool operator()(node* p1, node* p2) const { return p1->k > p2->k; } }; node *s[MAX*3]; priority_queue<node *,deque<node *>,nodeCmp> pro_queue; int main() { // freopen("ayjs.txt","r",stdin); int i,a; for(i=0;i<8;i++) { cin>>a; node *p; p=new node(a,str[i]); s[i]=p; pro_queue.push(s[i]); } while(pro_queue.size()>1) { node *p,*q,*k; p=pro_queue.top(); pro_queue.pop(); q=pro_queue.top(); pro_queue.pop(); k=uni(p,q); pro_queue.push(k); } node *p=pro_queue.top(); prim(p,0); for(int i=0;i<8;i++) { cout<<str[i]<<": "; for(int j=1;j<=str2[str[i]][0];j++) { cout<<str2[str[i]][j]; } cout<<endl; } cin>>str3; int len=str3.length(); for(int i=0;i<len;i++) { for(int j=1;j<=str2[str3[i]][0];j++) { cout<<str2[str3[i]][j]; } } cout<<endl; cin>>str3; len=str3.length(); node *q=pro_queue.top(); for(int i=0;i<len;i++) { if(str3[i]=='1') { q=q->r; } else { q=q->l; } if(q->c!='0') { cout<<q->c; q=pro_queue.top(); } } return 0; }
小结 : 哈夫曼编码的正确性证明见blog:
描述
有一些A、C、M组成的字符串,将其按字符A排序。
输入
一组测试数据,输入数据由若干行组成,每行是字符A、C或M组成的字符串。
输出
对所有输入的数据,先按字符A的个数进行升序排序,如果字符A的数量相等,再按出现的先后顺序排序,每行输出一个字符串。
样例输入
ACM
MCA
AACAAMMM
AACCMM
CMAAMMMMMM
AAA
样例输出
ACM
MCA
AACCMM
CMAAMMMMMM
AAA
AACAAMMM
#include<iostream> #include<math.h> #include<string> #define MAX 1001 using namespace std; struct node { char ch[10001]; int l; int c; }; struct node str[MAX]; int f(const void *a,const void *b) { if(((struct node *)a)->l==((struct node *)b)->l) return ((struct node *)a)->c-((struct node *)b)->c; return ((struct node *)a)->l-((struct node *)b)->l ; } int main() { int i=0,j,n; //freopen("fuck.txt","r",stdin); while(scanf("%s",&str[i].ch)!=EOF) { getchar(); n=strlen(str[i].ch); str[i].l=0; str[i].c=i; for(j=0;j<n;j++) { if(str[i].ch[j]=='A') str[i].l++; } i++; } n=i; qsort(str,n,sizeof(struct node),f); for(i=0;i<n;i++) cout<<str[i].ch<<endl; return 0; }
描述
将01串首先按长度排序,长度相同时,按1的个数多少进行排序,1的个数相同时再按ASCII码值排序。
输入
输入数据中含有一些01串,01串的长度不大于256个字符。
输出
重新排列01串的顺序。使得串按基本描述的方式排序。
样例输入
10011111
00001101
1010101
1
0
1100
样例输出
0
1
1100
1010101
00001101
10011111
#include<iostream> using namespace std; bool f(char *p1,char *p2) { int len1,num1,num2,i; num1=num2=0; if(strlen(p1)>strlen(p2)) return true; else if(strlen(p1)<strlen(p2)) return false; else { len1=strlen(p1); for(i=0;i<len1;i++) { num1+=p1[i]-'0'; num2+=p2[i]-'0'; } if(num1>num2) return true; else { if(num1<num2) return false; else { if(strcmp(p1,p2)<0) return true; else return false; } } } } int main() { int i=0; int j,n; char temp[280]; char str[2000][280]; while(scanf("%s",&str[i])!=EOF) { i++; } n=i; for(i=n-1;i>=0;i--) { for(j=0;j<i;j++) { if(f(str[j],str[j+1])) { strcpy(temp,str[j]); strcpy(str[j],str[j+1]); strcpy(str[j+1],temp); } } } for(i=0;i<n;i++) { cout<<str[i]<<endl; } return 0; }
描述
自然数中,完数寥若晨星,请在从1到某个整数范围中打印出所有的完数来。所谓“完数”是指一个数恰好等于它的所有不同因子之和。例如,6是完数,因为6=1+2+3。而24不是完数,因为24≠1+2+3+4+6+8+12=36。
输入
输入数据中含有一些整数n(1<n<10000)。
输出
对于每个整数n,输出所有不大于n的完数。每个整数n的输出由n引导,跟上冒号,然后是由空格开道的一个个完数,每个n的完数列表应占独立的一行。
样例输入
100
5000
样例输出
100: 6 28
5000: 6 28 496
#include<iostream> using namespace std; int main() { int n; while(scanf("%d",&n)!=EOF) { if(n>=8128) cout<<n<<": 6 28 496 8128"<<endl; else if(n>=496) cout<<n<<": 6 28 496"<<endl; else if(n>=28) cout<<n<<": 6 28"<<endl; else if(n>=6) cout<<n<<": 6"<<endl; else cout<<n<<":"<<endl; } return 0; }
描述
判断一个数是否为对称且不大于五位数的素数。
输入
输入数据含有不多于50个的正整数(0<n<2^32)。
输出
对于每个n,如果该数是不大于五位数的对称素数,则输出“Yes”,否则输出“No”。每个判断结果单独列一行。
样例输入
11 101 272
样例输出
Yes
Yes
No
#include<iostream> using namespace std; bool H[100000]; int str[115]={2,3,5,7,11,101,131,151,181,191,313,353,373,383,727,757,787,797,919,929,10301,10501,10601,11311,11411,12421,12721,12821,13331,13831,13931,14341,14741,15451,15551,16061,16361,16561,16661,17471,17971,18181,18481,19391,19891,19991,30103,30203,30403,30703,30803,31013,31513,32323,32423,33533,34543,34843,35053,35153,35353,35753,36263,36563,37273,37573,38083,38183,38783,39293,70207,70507,70607,71317,71917,72227,72727,73037,73237,73637,74047,74747,75557,76367,76667,77377,77477,77977,78487,78787,78887,79397,79697,79997,90709,91019,93139,93239,93739,94049,94349,94649,94849,94949,95959,96269,96469,96769,97379,97579,97879,98389,98689}; void f() { for(int i=0;i<115;i++) { H[str[i]]=1; } } int main() { int flag,i,a; f(); while(scanf("%d",&a)==1) { if(H[a]) printf("Yes\n"); else printf("No\n"); } return 0; }
小结 : ~~又是打表,还是手打的..
之后的题目,挑有的说的慢慢更新~