树图


寻找大富翁(25 分)

2015年胡润研究院的调查显示,截至2014年9月,个人资产在600万元以上高净值人群达290万人。假设给出N个人的个人资产值,请快速找出资产排前M位的大富翁。

输入格式:

输入首先给出两个正整数N106)和M10),其中N为总人数,M为需要找出的大富翁数;接下来一行给出N个人的个人资产值,以百万元为单位,为不超过长整型范围的整数。数字间以空格分隔。

输出格式:

在一行内按非递增顺序输出资产排前M位的大富翁的个人资产值。数字间以空格分隔,但结尾不得有多余空格。

输入样例:

8 3
8 12 7 3 20 9 5 18

输出样例:

20 18 12
思路:输入数据——>排序输出 唯一需要注意的一点即是正整数N是小于10的6次方的 int是放不下的 需要用long int[]

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
long int money[1000001];	//定义资产值
int main(){
	int n,m,t;
	cin>>n>>m;
	if(n<m){	//其中代码检测有这么一点:n小于m——> n小于m就调换位置让n大于m呗...
		t=n;
		n=m;
		m=t;
	} 
	for(int i=0;i<n;i++){
		scanf("%d",&money[i]);
	}
	sort(money,money+n);	//sort函数 头文件是#include<algorithm>
	for(int i=n-1;i>n-m;i--){	//输出财富值最大的M个人,并且最后一个不能有空格
		printf("%d ",money[i]);
	}
	printf("%d\n",money[n-m]);
}


抢红包(25 分)

没有人没抢过红包吧…… 这里给出N个人之间互相发红包、抢红包的记录,请你统计一下他们抢红包的收获。

输入格式:

输入第一行给出一个正整数N104),即参与发红包和抢红包的总人数,则这些人从1到N编号。随后N行,第i行给出编号为i的人发红包的记录,格式如下:

KN1P1NKPK

其中K0K20)是发出去的红包个数,Ni是抢到红包的人的编号,Pi>0)是其抢到的红包金额(以分为单位)。注意:对于同一个人发出的红包,每人最多只能抢1次,不能重复抢。

输出格式:

按照收入金额从高到低的递减顺序输出每个人的编号和收入金额(以元为单位,输出小数点后2位)。每个人的信息占一行,两数字间有1个空格。如果收入金额有并列,则按抢到红包的个数递减输出;如果还有并列,则按个人编号递增输出。

输入样例:

10
3 2 22 10 58 8 125
5 1 345 3 211 5 233 7 13 8 101
1 7 8800
2 1 1000 2 1000
2 4 250 10 320
6 5 11 9 22 8 33 7 44 10 55 4 2
1 3 8800
2 1 23 2 123
1 8 250
4 2 121 4 516 7 112 9 10

输出样例:

1 11.63
2 3.63
8 3.63
3 2.11
7 1.69
6 -1.67
9 -2.18
10 -3.26
5 -3.26
4 -12.32
思路:结构体存储一个人对应的id、抢红包赚的钱take和抢红包的数量count。之后将相应id的用户take值相加,并减去id用户发的值,最后即是总take的值。
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
	double take;//抢的钱
	int id;//用户id
	int count;//发包数量
}people[10001];
int cmd(struct node a,struct node b){//自定义排序
	if(a.take!=b.take)//按抢到的金额降序排列
		return a.take>b.take;
	else if(a.count!=b.count)//如果金额相同 按抢包的数量降序排列
		return a.count>b.count;
	else if(a.id!=b.id)
		return a.id<b.id;//如果发包数量也相同 按id小的排序
} 
int main(){
	int n,k;
	cin>>n;
	for(int i=0;i<=n;i++){//首先将每个人的take、count赋值为0,对应的id赋值给i。
		people[i].take=0;
		people[i].count=0;
		people[i].id=i;
	}
	for(int i=1;i<=n;i++){//n个人的循环
		cin>>k;
		double sum=0;//记录总发的红包的金额总数
		for(int j=1;j<=k;j++){//发k个红包的循环
			int id;
			double money=0;
			cin>>id>>money;
			people[id].take += money/100.0;//对应id的人take的值
			people[id].count++;//对应id的人抢红包count值
			sum+=money;//把发的红包金额加和
		}
		people[i].take-=sum/100.0;//发包的这个用户的take值要减去自己发红包的金额 赚的钱=抢的钱-发的钱
	} 
	sort(people+1,people+n+1,cmd);			
	for(int i=1;i<=n;i++){
		printf("%d %.2lf\n",people[i].id,people[i].take);
	}
}



互评成绩(25 分)

学生互评作业的简单规则是这样定的:每个人的作业会被k个同学评审,得到k个成绩。系统需要去掉一个最高分和一个最低分,将剩下的分数取平均,就得到这个学生的最后成绩。本题就要求你编写这个互评系统的算分模块。

输入格式:

输入第一行给出3个正整数N(3 < N 104,学生总数)、k(3  k  10,每份作业的评审数)、M 20,需要输出的学生数)。随后N行,每行给出一份作业得到的k个评审成绩(在区间[0, 100]内),其间以空格分隔。

输出格式:

按非递减顺序输出最后得分最高的M个成绩,保留小数点后3位。分数间有1个空格,行首尾不得有多余空格。

输入样例:

6 5 3
88 90 85 99 60
67 60 80 76 70
90 93 96 99 99
78 65 77 70 72
88 88 88 88 88
55 55 55 55 55

输出样例:

87.667 88.000 96.000
思路:记录下来每个同学的得分,去掉最高和最低取平均值,存放在数组后,排序输出最高的M个成绩
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
	int n,k,m;
	cin>>n>>k>>m;
	double score[11];//存成绩
	double avg[100001];//存平均成绩
	for(int i=0;i<n;i++){//n个学生
		double sum=0;//记录学生去掉最高和最低分成绩的总和
		for(int j=0;j<k;j++)//每个学生有k个成绩
		cin>>score[j];//输入k个成绩
		sort(score,score+k);//对k个成绩排序
		for(int l=1;l<k-1;l++)//去掉最高的、最低的成绩
		sum+=score[l];
		avg[i]=sum/(k-2);//去掉最高最低分数后的平均分
	}
	sort(avg,avg+n);
	for(int i=n-m;i<n-1;i++){//输出M个最高分 最后一个不要空格
		printf("%.3lf ",avg[i]);
	}
	printf("%.3lf\n",avg[n-1]);
}




树的同构(25 分)

给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。


图1


图2

现给定两棵树,请你判断它们是否是同构的。

输入格式:

输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数N (10),即该树的结点数(此时假设结点从0到N1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出“-”。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。

输出格式:

如果两棵树是同构的,输出“Yes”,否则输出“No”。

输入样例1(对应图1):

8
A 1 2
B 3 4
C 5 -
D - -
E 6 -
G 7 -
F - -
H - -
8
G - 4
B 7 6
F - -
A 5 1
H - -
C 0 -
D - -
E 2 -

输出样例1:

Yes

输入样例2(对应图2):

8
B 5 7
F - -
A 0 3
C 6 -
H - -
D - -
G 4 -
E 1 -
8
D 6 -
B 5 -
E - -
H - -
C 0 2
G - 3
F - -
A 1 4

输出样例2:

No
思路:我们通过输入样例可以发现,输入的左右子树的序列也就是节点的编号,所以我们可以通过下标来访问数组得到左右子树。https://blog.csdn.net/wanmeiwushang/article/details/52740354附大神帖子,感谢。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#define Null -1	
using namespace std;
typedef struct Tree{
	char data;
	int lchild,rchild;
}T;
Tree t1[11],t2[11];
int check[11];		//check数组用来寻找树的根节点
int n;			//n个结点
int create(Tree T[]){
	int root=Null;	//刚开始结点置为Null,若为空树是可以设置为Null
	int i;
	cin>>n;
	char l,r;
	if(n){ 		//如果不是空树
		for(i=0;i<n;i++)
		check[i]=0;	//将check置为0.
		for(i=0;i<n;i++){
			cin>>T[i].data>>l>>r;
			if(l!='-'){
				T[i].lchild=l-'0';	
				check[T[i].lchild]=1;		//根据左子树对应的序列找到节点。
			}
			else
			T[i].lchild=Null;
			if(r!='-'){
				T[i].rchild=r-'0';
				check[T[i].rchild]=1;
			}
			else
			T[i].rchild=Null;
		}
		for(i=0;i<n;i++){
			if(!check[i])
			break;
		}
		root=i;
	}
	return root;
}
bool isTongGou(int r1,int r2){
	if(r1==Null&&r2==Null)		//如果都为空树则同构
	return true;
	if(((r1==Null)&&(r2!=Null)) || ((r1!=Null)&&(r2==Null)))	//如果一个为空、一个不为空则不同构
	return false;
	if((t1[r1].data)!=(t2[r2].data))				//如果数据不同不为同构
	return false;
	if((t1[r1].lchild==Null) && (t2[r2].lchild==Null))		//如果左儿子都为空判断右儿子是否同构:主要看以上三个方面(1)右儿子是否都为空(2)是否一个有右儿子一个没有(3)右儿子数据是否相同
	return isTongGou(t1[r1].rchild,t1[r2].rchild);
	/* 如果两棵树左儿子都不为空并且数据还是一样的,对左儿子进行递归*/
	if((t1[r1].lchild!=Null) && (t2[r2].lchild!=Null) &&(t1[t1[r1].lchild].data)==(t2[t2[r2].lchild].data))
	return isTongGou(t1[r1].lchild,t2[r2].lchild)&&isTongGou(t1[r1].rchild,t2[r2].rchild);
	/* 如果两棵树左儿子(一个空一个不空或者都不空)并且数据不一样,那么判断第一棵树的左(右)儿子是否跟第二棵树的右(左)儿子同构 */
	else
	return isTongGou(t1[r1].rchild,t2[r2].lchild)&&isTongGou(t1[r1].lchild,t2[r2].rchild);
}
int main(){
	int R1,R2;
	R1=create(t1);
	R2=create(t2);
	if(isTongGou(R1,R2))
	printf("Yes\n");
	else
	printf("No\n");
	
}






还原二叉树(25 分)

给定一棵二叉树的先序遍历序列和中序遍历序列,要求计算该二叉树的高度。

输入格式:

输入首先给出正整数N(50),为树中结点总数。下面两行先后给出先序和中序遍历序列,均是长度为N的不包含重复英文字母(区别大小写)的字符串。

输出格式:

输出为一个整数,即该二叉树的高度。

输入样例:

9
ABDFGHIEC
FDHGIBEAC

输出样例:

5
思路:前中序建树、查树深
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
char qian[10000];
char zhong[10000];
struct Tree{
	char data;
	struct Tree *left,*right;
};
struct Tree *create(int q,int z,int n){
	struct Tree *T;
	int i;
	if(n<=0){
		T=NULL;
	}
	else{
		T=(struct Tree*)malloc(sizeof(struct Tree));//首先要给T分配空间,才能让T放数据。
		T->data = qian[q];
		for(i=0;qian[q]!=zhong[z+i];i++);//这行不太懂
		T->left = create(q+1,z,i);
		T->right = create(q+i+1,z+i+1,n-i-1);
	}
	return T;
}
int Depth(struct Tree *T){
	int m=0,n=0;
	if(T){
		m=Depth(T->left);
		n=Depth(T->right);
		if(n<m)
		return m+1;//不论哪个大都是大的+1,还包括根这一层
		else
		return n+1;
	}
	else
	return 0;
}
int main(){
	struct Tree *T;
	int n,i,p;
	cin>>n;
	for(i=0;i<n;i++){
		cin>>qian[i];
	}
	for(i=0;i<n;i++){
		cin>>zhong[i];
	}
	T=create(0,0,n);
	p=Depth(T);
	cout<<p<<endl;
}


7-11 是否同一棵二叉搜索树(25 分)

给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果。于是对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树。

输入格式:

输入包含若干组测试数据。每组数据的第1行给出两个正整数N (10)和L,分别是每个序列插入元素的个数和需要检查的序列个数。第2行给出N个以空格分隔的正整数,作为初始插入序列。最后L行,每行给出N个插入的元素,属于L个需要检查的序列。

简单起见,我们保证每个插入序列都是1到N的一个排列。当读到N为0时,标志输入结束,这组数据不要处理。

输出格式:

对每一组需要检查的序列,如果其生成的二叉搜索树跟对应的初始序列生成的一样,输出“Yes”,否则输出“No”。

输入样例:

4 2
3 1 4 2
3 4 1 2
3 2 4 1
2 1
2 1
1 2
0

输出样例:

Yes
No
No
思路:用两个数组模拟两棵树,插入就按二叉搜索树的要求:是空树,或者始终保持左子树比根节点要小(左节点的序列是2倍的根节点),右子树要比根节点要大(右节点的序列是2倍+1的根节点)。插入完成之后就比较两个数组的值是否完全相等,相等则代表是,不相等则代表不是。
#include<bits/stdc++.h>	//万能头文件 
using namespace std;
int insert(int t[],int input){	//插入,两棵树分两次插入,input代表插入的元素 
	int i=1;
	if(t[1]==0){	//如果此时是空树,就把第一个输入的节点作为根节点 
		t[1]=input;
		return 0;
	}
	while(1){	
		if(input>=t[i])		//如果输入的该节点大于根,放在右子树 
		i=i*2+1;
		if(input<t[i])		//否则放在左子树 
		i=i*2;
		if(t[i]==0){		//如果当前的左右子树下没有子节点,那么这个左右子树又作为新的根 
			t[i]=input;		
			break;
		}
	}
	return 0;
}
void input(int t[],int n){	//输入数据 t代表树,n代表元素个数 
	int i,temp;
	for(int i=1;i<=n;i++){
		scanf("%d",&temp);
		insert(t,temp);
	}
}
int compare(int t1[],int t2[],int max){		//两树比较 
	int i;
	for(i=1;i<max;i++){		//在某个范围内比较 
		if(t1[i]!=t2[i])	//如果不等于就-1 
		return -1;
	}
	return 0;
} 
int main()
{
    int n,l,i;
    while(1)
    {
        scanf("%d",&n);
        if(n==0) exit(0);
        scanf("%d",&l);
        int t1[9999]={0};
        input(t1,n);
        for(i=1;i<=l;i++)
        {
            int t2[9999]={0};
            input(t2,n);
            if(compare(t1,t2,9998)==0) printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}


7-14 树种统计(25 分)

随着卫星成像技术的应用,自然资源研究机构可以识别每一棵树的种类。请编写程序帮助研究人员统计每种树的数量,计算每种树占总数的百分比。

输入格式:

输入首先给出正整数N(105),随后N行,每行给出卫星观测到的一棵树的种类名称。种类名称由不超过30个英文字母和空格组成(大小写不区分)。

输出格式:

按字典序递增输出各种树的种类名称及其所占总数的百分比,其间以空格分隔,保留小数点后4位。

输入样例:

29
Red Alder
Ash
Aspen
Basswood
Ash
Beech
Yellow Birch
Ash
Cherry
Cottonwood
Ash
Cypress
Red Elm
Gum
Hackberry
White Oak
Hickory
Pecan
Hard Maple
White Oak
Soft Maple
Red Oak
Red Oak
White Oak
Poplan
Sassafras
Sycamore
Black Walnut
Willow

输出样例:

Ash 13.7931%
Aspen 3.4483%
Basswood 3.4483%
Beech 3.4483%
Black Walnut 3.4483%
Cherry 3.4483%
Cottonwood 3.4483%
Cypress 3.4483%
Gum 3.4483%
Hackberry 3.4483%
Hard Maple 3.4483%
Hickory 3.4483%
Pecan 3.4483%
Poplan 3.4483%
Red Alder 3.4483%
Red Elm 3.4483%
Red Oak 6.8966%
Sassafras 3.4483%
Soft Maple 3.4483%
Sycamore 3.4483%
White Oak 10.3448%
Willow 3.4483%
Yellow Birch 3.4483%
思路:map容器 <string,int>储存树名和次数
#include<bits/stdc++.h>  
using namespace std;
int main(){
	map<string,int> m;	//map容器 
	int n;
	cin>>n;
	string str;
	getchar();	//必须getchar(),否则回车换行将被getline()吃掉
	for(int i=0;i<n;i++){
		getline(cin,str);
		if(m.find(str)==m.end()){
			m[str]=1;
		}
		else{
			m[str]++;
		}
	}
	map<string,int>::iterator it=m.begin();
	for(;it!=m.end();it++){
		cout<<it->first<<" ";
		printf("%.4lf%%\n",it->second/(double)(n)*100);
	}
}
Map:

1、map是一对一的,键值是唯一的,另外一个可能是对应键值的某个数。就好比在一个班级中,学生姓名对应唯一一个学号。该题是数名是唯一的。

2、map提供自动排序。

3、map的构造方法:(来自百度百科) map的头文件:#include<map>

map<int,string> maphai;
map<char,int> maphai;
map<string,char> mapstring;
map<string,int> mapstring;
map<int,char>mapint;
map<char,string>mapchar;

4、map的插入:

对于map<string, int>map_str,有以下几种插入方式:

map_str.insert(make_pair("key", 23));             // 将键值对{"key", 23}插入到映射中

map_str.insert({"key", 23});                          // 将键值对{"key", 23}插入到映射中

map_str.insert(map_str.begin()+2, make_pair("key", 23));   // 在第二个位置插入{"key", 23}键值对

5、map成员函数

at
查找具有指定键值的元素。
begin 返回一个迭代器,此迭代器指向映射中的第一个元素。
cbegin 返回一个常量迭代器,此迭代器指向映射中的第一个元素。
cend 返回一个超过末尾常量迭代器。
clear 清除映射的所有元素。
count 返回映射中其键与参数中指定的键匹配的元素数量。
crbegin 返回一个常量迭代器,此迭代器指向反向映射中的第一个元素。
crend 返回一个常量迭代器,此迭代器指向反向映射中最后一个元素之后的位置。
emplace 将就地构造的元素插入到映射。
emplace_hint 将就地构造的元素插入到映射,附带位置提示。
empty 如果映射为空,则返回 true。
end 返回超过末尾迭代器。
equal_range 返回一对迭代器。 此迭代器对中的第一个迭代器指向 map 中其键大于指定键的第一个元素。 此迭代器对中的第二个迭代器指向 map 中其键等于或大于指定键的第一个元素。
erase 从指定位置移除映射中的元素或元素范围。
find 返回一个迭代器,此迭代器指向映射中其键与指定键相等的元素的位置。
get_allocator 返回用于构造映射的 allocator 对象的副本。
insert 将元素或元素范围插入到映射中的指定位置。
key_comp 返回用于对映射中的键进行排序的比较对象副本。
lower_bound 返回一个迭代器,此迭代器指向映射中其键值等于或大于指定键的键值的第一个元素。
max_size 返回映射的最大长度。
rbegin 返回一个迭代器,此迭代器指向反向映射中的第一个元素。
rend 返回一个迭代器,此迭代器指向反向映射中最后一个元素之后的位置。
size 返回映射中的元素数量。
swap 交换两个映射的元素。
upper_bound 返回一个迭代器,此迭代器指向映射中其键值大于指定键的键值的第一个元素。
value_comp 检索用于对映射中的元素值进行排序的比较对象副本。
shrink_to_fit 放弃额外容量。
size 返回vector元素个数
swap 交换两个向量的元素。

6、

cin不接受空格,TAB等键的输入,遇到这些键,字符串会终止,而gets()则接受连续的输入,包括空格,TAB;

gets()只能读取char类型,例如char s[10],gets(s);

gets()不能读取string类型;

string类型可用getline(),例如string s,getline(cin,s);

getchar()是用来吃掉回车符号的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值