数据结构与算法训练:第二十六章

1. 知识点总结

耗时:2h

得分:100/100

知识点:树的层次遍历、字符串处理和哈希表(二次探查解决冲突)

题目难度知识点
1076 Forwards on Weibo🎯🎯层次遍历树
1077 Kuchiguse🎯字符串处理
1078 Hashing🎯哈希表解决冲突
1079 Total Sales of Supply Chain🎯层次遍历树

2. 分题题解

2.1 1076 Forwards on Weibo

这题的主要难点在于计算forwards的英文理解,也就是先根据题干构建好图的结构之后,层次遍历求解每一层forwrd的总人数,一共需要计算[1,L]层的总人数,默认当前被询问的节点是第0层.

卡了半小时,原因是我理解的indirect是和当前节点没有直接边的,但是最后AC的版本中可以看到,题目的indirect指的是非当前节点本身.

#include<bits/stdc++.h>
using namespace std;
int N,L,K,num,id,fid;
struct Node{
	int level;
	vector<int>followers;
}; 
vector<Node>nodes;
vector<bool>vis;
void levelCount(int root){
	int cnt=0;
	fill(vis.begin(),vis.end(),false);
	queue<int>q;
	q.push(root);
	vis[root]=true;
	nodes[root].level=0;
	while(!q.empty()){
		int top=q.front();
		q.pop();
		//bprintf("level:%d val:%d\n",nodes[top].level,top);
		if(nodes[top].level<=L){
			cnt++;
		}else{
			break;
		}
		for(int i=0;i<nodes[top].followers.size();i++){
			int cid=nodes[top].followers[i];
			if(!vis[cid]){
				vis[cid]=true;
				nodes[cid].level=nodes[top].level+1;
				q.push(cid);
			}
		}
	}
	printf("%d",cnt-1);
}
int main(){
	scanf("%d%d",&N,&L);
	nodes.resize(N+1);
	vis.resize(N+1,false);
	for(int i=1;i<=N;i++){
		scanf("%d",&num);
		for(int j=0;j<num;j++){
			scanf("%d",&fid);
            //构建图结构
			nodes[fid].followers.push_back(i);
		}
	}
	scanf("%d",&K);
	while(K--){
		//处理
		scanf("%d",&id);
		levelCount(id);
		if(K){
			printf("\n");
		}	 
	}
	return 0;
}

2.2 1077 Kuchiguse

找出给定字符串的最长公共后缀,属于基础题~

#include<bits/stdc++.h>
using namespace std;
int N;
//输出最长的公共子串
vector<string>strs; 
string ans;
void getSuffix(string a,string& b){
	int lena=a.length();
	int lenb=b.length();
	int i;
	string c="";
	for(i=0;i<min(lena,lenb);i++){
		if(a[lena-i-1]!=b[lenb-i-1]){
			break;
		}else{
			c+=a[lena-i-1];
		}
	}
	reverse(c.begin(),c.end());
	b=c;
}
int main(){
	scanf("%d",&N);
	strs.resize(N);
	getchar();
	for(int i=0;i<N;i++){
		getline(cin,strs[i]);
	}
	ans=strs[0];
	for(int i=1;i<N;i++){
		getSuffix(strs[i],ans);
		if(ans==""){
			break;
		}
	}
	//输出答案
	if(ans==""){
		printf("nai");
	}else{
		printf("%s",ans.c_str());
	}
	return 0;
} 

2.3 1078 Hashing

哈希表二次探查解决冲突,主要难点在于英文Quadratic probing (with positive increments only) is used to solve the collisions.的理解:二次探测(仅具有正增量)用于解决冲突。(来自百度翻译)

#include<bits/stdc++.h>
using namespace std;
int MSize,N,temp;
bool isPrime(int x){
	if(x<=1)return false;
	if(x==2||x==3||x==5||x==7){
		return true;
	}
	for(int i=2;i*i<=x;i++){
		if(x%i==0){
			return false;
		}
	}
	return true;
}
vector<int>table;
int Hash(int x){
	int pos=-1;
	for(int i=0;i<MSize;i++){
		int tpos=(i*i+x)%MSize;
		if(table[tpos]==-1){
			pos=tpos;
			break;
		}
	}
	return pos;
}
int main(){
	scanf("%d%d",&MSize,&N);
	while(!isPrime(MSize)){
		MSize++;
	}
	table.resize(MSize,-1);
	for(int i=0;i<N;i++){
		scanf("%d",&temp);
		//hash查找位置
		int pos=Hash(temp);
		if(i){
			printf(" ");
		}
		if(pos==-1){
			printf("-");
		}else{
			table[pos]=temp;
			printf("%d",pos);
		}
	}
	return 0;
}

2.4 1079 Total Sales of Supply Chain

这个背景的题干遇到很多次了,都是层次遍历树的变式,主要是构建好树之后输出叶子节点价格x货量的总和

#include<bits/stdc++.h>
using namespace std;
int N,root=0;
double P,r,total_price=0;
struct Node{
	int K;
	double price;
	int sum;
	vector<int>childs;
};
vector<Node>nodes;
void levelTravel(int root){
	queue<int>q;
	nodes[root].price=P;
	q.push(root);
	while(!q.empty()){
		int top=q.front();
		q.pop();
		for(int i=0;i<nodes[top].K;i++){
			int cid=nodes[top].childs[i];
			nodes[cid].price=nodes[top].price*(1+r/100);
			q.push(cid);
		}
		if(nodes[top].K==0){
			total_price+=nodes[top].price*nodes[top].sum;
		}
	}
}
int main(){
	scanf("%d%lf%lf",&N,&P,&r);
	nodes.resize(N);
	for(int i=0;i<N;i++){
		scanf("%d",&nodes[i].K);
		if(nodes[i].K==0){
			scanf("%d",&nodes[i].sum);
			continue;
		}
		nodes[i].childs.resize(nodes[i].K);
		for(int j=0;j<nodes[i].K;j++){
			scanf("%d",&nodes[i].childs[j]);
		}
	}
	levelTravel(root);
	printf("%.1f",total_price);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值