2019年北邮机试真题

A、 二进制

Time Limit: 1000 ms
Memory Limit: 256 mb
有一个长度为32位的二进制数X,对其进行X+1,X+3 操作,并输出。注意不能忽略前导0

输入输出格式
输入描述:
第一行,一个整数T,代表测试数据组数。
接着T行,输入32为二进制数
输出描述:
对每组测试数据,输出两行,第一行为X+1,第二行为X+3.

输入输出样例
输入样例#:
2
00000000000000000000000000000000
00000000000000000000000000000001
输出样例#:
00000000000000000000000000000001
00000000000000000000000000000011
00000000000000000000000000000010
00000000000000000000000000000100
提示
如果长度超过32位就不用前导0

题目来源
北京邮电大学2019年机试题
真题链接在此

思路:就是从低位向高位进行处理,然后注意进位即可。坑:11111111111111111111111111111111的结果是100000000000000000000000000000000(输出33位)和100000000000000000000000000000010(输出33位)

#include<iostream> 
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int main(){
	int t;
	cin>>t;
	string h;
	for(int i=1;i<=t;i++){
		cin>>h;
		int k=1;
		int mark=0;
		for(int j=31;j>=0;j--){
			int ll=h[j]-'0'+k;
			if(ll==2){
				if(j==0)
					mark=1;
				k=1;
				h[j]='0';
			}
			else{
				h[j]='0'+ll;
				k=0;
			}
		}
		if(mark==0)
			cout<<h<<endl;
		else{
			cout<<1;
			for(int u=0;u<32;u++)
				cout<<h[u];
			cout<<endl;
		}
		k=1;
		for(int j=30;j>=0;j--){
			int ll=h[j]-'0'+k;
			if(ll==2){
				k=1;
				h[j]='0';
			}
			else{
				h[j]='0'+ll;
				k=0;
			}
		}
		if(mark==0)
			cout<<h<<endl;
		else{
			cout<<1;
			for(int u=0;u<32;u++)
				cout<<h[u];
			cout<<endl;
		}
	}
	return 0;
}

B、二叉树

Time Limit: 1000 ms
Memory Limit: 256 mb
对二叉树,计算任意两个结点的最短路径长度。

输入描述:
第一行输入测试数据组数 T
第二行输入 n , m 。 n 代表输入的数据组数, m 代表要查询的数据组数。
接下来 n 行,每行输入两个数,代表1~ n 结点的孩子结点,如果没有孩子结点则输入-1,根节点为1。
接下来 m 行,每行输入两个数,代表要查询的两个结点。
输出描述:
每组测试数据输出 m 行,代表查询的两个结点之间的最短路径长度。

输入输出样例
输入样例#:
1
8 4
2 3
4 5
6 -1
-1 -1
-1 7
-1 -1
8 -1
-1 -1
1 6
4 6
4 5
8 1
输出样例#:
2
4
2
4

题目来源
北京邮电大学2019年机试题
真题链接在此

思路:用len数组记录当前节点的深度,findRoot函数是记录当前节点的父亲节点。我们可以让两个目标节点同时向上找第一个相同的祖先节点,当找到第一个相同的祖先节点时,第一个节点到祖先节点的距离+第二个节点到祖先节点的距离就是两个节点之间的最小距离。我们每一次找祖先节点的时候都是首先操作在树中更深的节点,因为有可能另一个节点就是当前节点的祖先节点,为了避免错过这个节点所以不可以两边的节点同时向上找共同的祖先节点。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int father[505];
int len[505];
int dis;
void findRoot(int a,int b){
	if(a==b)
		return;
	dis++;
	if(len[a]>=len[b])
		findRoot(father[a],b);
	else if(len[a]<len[b])
		findRoot(a,father[b]);
	return;
}
int main(){
	int t;
	cin>>t;
	while(t--){
		memset(father,0,sizeof(father));
		memset(len,0,sizeof(len));
		father[1]=-1;
		len[1]=1;
		int n,k;
		cin>>n>>k;
		for(int i=1;i<=n;i++){
			int a,b;
			cin>>a>>b;
			if(a!=-1){
				father[a]=i;
				len[a]=len[i]+1;
			}
			if(b!=-1){
				father[b]=i;
				len[b]=len[i]+1;
			} 
		}
		for(int i=0;i<k;i++){
			int a,b;
			cin>>a>>b;
			dis=0;
			findRoot(a,b);
			cout<<dis<<endl;
		} 
	}
	return 0;
} 

C、最短路径

Time Limit: 1000 ms
Memory Limit: 256 mb
有n(n<=50)个城市,保证每个城市与其他城市之间必然有连接,但是两个城市之间会存在多条道路,输入道路连接的两个城市号及道路长度。同时在夜晚,某些道路会封路。请输出在白天和夜晚从城市1到城市n之间的最短路径

输入描述:
先输入T,表示有T组数据
再输入n,m,k,n表示有n个城市,表示总共有m条边,k表示在夜晚有k条路封路
接下来m行,每行输入三个数x,y,z,代表城市x和城市y之间的路径距离
最后一行k个数,代表晚上关闭的线路序号(线路序号指的是1~m)
输出描述:
每组数据输出两行,分别代表白天和黑夜,城市1到n的最短路径

输入样例#:
1
4 4 1
1 2 1
2 3 1
3 4 1
1 4 1
4
输出样例#:
1
3

题目来源
北京邮电大学2019年机试题
真题链接在此

思路:就是最普通的单源最短路,当然不想写Dijkstra的也可以直接上Floyd,不会超时。除了最短路的板子,就是一开始对数据的预处理了,用Floyd的话,邻接矩阵是一个对阵矩阵,一开始令所有元素均为无穷大,然后读入m条边,并修改邻接矩阵中对应的值,注意因为是对称矩阵所以一次性修改两个值,坑点1:因为两个城市之间不止一条路,所以要记录两个城市之间距离最小的那条,然后跑一次最短路即可。接下来是晚间,因为晚上有的路不能走,所以我们要令相对应的路的值为无穷大。坑点2:因为我们之前在第一次最短路操作时已经对邻接矩阵中的很多值进行了修改,再进行一次新的最短路,应该先令邻接矩阵的值都为无穷大,然后再一次遍历那m条边,操作和第一次一样,但是一些路已经是无穷大了即晚间不可通行,这里不用特殊处理这些路(坑点2我自己踩了,debug到头秃,值得注意别粗心)。总体思路就是两次最短路,但要注意数据预处理。

不知道最短路怎么写的,可移步我的另一篇博客,里面有多种最短路的算法
最短路的各种算法小节链接在此

Floyd版本

#include<iostream>
using namespace std;
struct node {
	int x,y,z;
};
int main()
{
	int t;
	cin>>t;
	for(int i=1; i<=t; i++) {
		int h[500][500];
		node p[500];
		int n,m,kk;
		cin>>n>>m>>kk;
		int num1;
		for(int j=1; j<=n; j++){
			for(int k=1; k<=n; k++){
				h[j][k]=99999999;
				h[k][j]=99999999;
			}
		}
		for(int j=1; j<=m; j++) {
			cin>>p[j].x>>p[j].y>>p[j].z;
			int ll=h[p[j].x][p[j].y];
			if(p[j].z<ll) {
				h[p[j].x][p[j].y]=p[j].z;
				h[p[j].y][p[j].x]=p[j].z;
			}
		}
		for(int k1=1;k1<=n;k1++)
			for(int i1=1;i1<=n;i1++)
				for(int j1=1;j1<=n;j1++)
					if(h[i1][j1]>h[i1][k1]+h[k1][j1])
			    		h[i1][j1]=h[i1][k1]+h[k1][j1];
		num1=h[1][n];
		for(int j=1; j<=kk; j++) {
			int l;
			cin>>l;
			p[l].z=99999999;
			h[p[l].x][p[l].y]=99999999;
			h[p[l].y][p[l].x]=99999999;
		}
		//h数组全都要置为99999999因为第一次的floyed已经使得h中很多数据都改变了!!! 
		for(int j=1;j<=n;j++){
			for(int k=1;k<=n;k++){
				h[j][k]=99999999;
				h[k][j]=99999999;
			}
		}
		for(int j=1;j<=m;j++){
			if(h[p[j].x][p[j].y]>p[j].z){
				h[p[j].x][p[j].y]=p[j].z;
				h[p[j].y][p[j].x]=p[j].z;
			}
		}
		for(int k1=1;k1<=n;k1++)
			for(int i1=1;i1<=n;i1++)
				for(int j1=1;j1<=n;j1++)
					if(h[i1][j1]>h[i1][k1]+h[k1][j1])
			    		h[i1][j1]=h[i1][k1]+h[k1][j1];
		cout<<num1<<endl<<h[1][n]<<endl;
	}
	return 0;
}

Dijkstra版本

#include<iostream>
using namespace std;
struct node {
	int x,y,z;
};
int main()
{
	int t;
	cin>>t;
	for(int i=1; i<=t; i++) {
		int h[500][500];
		node p[500];
		int n,m,kk;
		cin>>n>>m>>kk;
		int num1;
		for(int j=1; j<=n; j++){
			for(int k=1; k<=n; k++){
				h[j][k]=99999999;
				h[k][j]=99999999;
			}
		}
		for(int j=1; j<=m; j++) {
			cin>>p[j].x>>p[j].y>>p[j].z;
			int ll=h[p[j].x][p[j].y];
			if(p[j].z<ll) {
				h[p[j].x][p[j].y]=p[j].z;
				h[p[j].y][p[j].x]=p[j].z;
			}
		}
		int dis[500];
		int book[500];
		for(int j=1; j<=n; j++)
			dis[j]=h[1][j];
		for(int j=1; j<=n; j++)
			book[j]=0;
		book[1]=1;
		int min;
		int u,v;
		for(int j=1; j<=n-1; j++) {
			min=99999999;
			for(int k=1; k<=n; k++) {
				if(book[k]==0&&dis[k]<min) {
					min=dis[k];
					u=k;
				}
			}
			book[u]=1;
			for(v=1; v<=n; v++) {
				if(h[u][v]<99999999) {
					if(dis[v]>dis[u]+h[u][v])
						dis[v]=dis[u]+h[u][v];
				}
			}
		}
		num1=dis[n];
		for(int j=1; j<=kk; j++) {
			int l;
			cin>>l;
			p[l].z=99999999;
		}
		for(int j=1;j<=n;j++){
			for(int k=1;k<=n;k++){
				h[j][k]=99999999;
				h[k][j]=99999999;
			} 
		} 
		for(int j=1;j<=m;j++){
			if(h[p[j].x][p[j].y]>p[j].z){
				h[p[j].x][p[j].y]=p[j].z;
				h[p[j].y][p[j].x]=p[j].z;
			}
		}
		for(int j=1; j<=n; j++)
			dis[j]=h[1][j];
		for(int j=1; j<=n; j++)
			book[j]=0;
		book[1]=1;
		for(int j=1; j<=n-1; j++) {
			min=99999999;
			for(int k=1; k<=n; k++) {
				if(book[k]==0&&dis[k]<min) {
					min=dis[k];
					u=k;
				}
			}
			book[u]=1;
			for(v=1; v<=n; v++) {
				if(h[u][v]<99999999) {
					if(dis[v]>dis[u]+h[u][v])
						dis[v]=dis[u]+h[u][v];
				}
			}
		}
		cout<<num1<<endl<<dis[n]<<endl;
	}
	return 0;
}

D、方块阵

Time Limit: 1000 ms
Memory Limit: 256 mb
给出一张从原图片中沿横纵向剪切后的图片,判断原图片中nn(n>=1)矩阵的大小
(原图片肯定存在该n
n的矩阵,且唯一)
举例说明
如果原图片是这样:
…###…
…###…
…###…


剪切后的图片可能是:
1)不变
…###…
…###…
…###…


2)
##…
##…
##…


所以一个原图片可能对应很多剪切后的图片

输入描述:
输入剪辑后的图片,长宽不会超过100
其中‘.’表示空白,’#'表示图片中矩阵的内容
输出描述:
输出原图片中最小n*n矩阵的大小,即n的值,如果不存在则输出-1

输入样例#:
##…
##…
##…


输出样例#:
3

题目来源
北京邮电大学2019年机试题
真题链接在此

思路:就是读入当前的字符矩阵,找出以行为单位找出含#最多的行有多少个#,然后以列为单位找出含#最多的列有多少个#,然后取两者的最大值即为n的值的大小,如果两者均为0,则可知找不到输出-1即可。关于输入的一个小问题,我们在DEV类似的编译器上运行该程序,可能会出现一直需要输入的情况,因为whlie中并没有退出的条件,因为题目中也没有给出输入什么时候可以判断结束,读者可以自行写一个退出while循环的条件,比如给的样例一共5行,我们可以令while循环执行5次退出即可,注意这只是调试的时候可以使用,提交的时候可以不用管while什么时候可以退出,直接交上就行,本人已经AC。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int main(){
	string h2;
	int num1=0;
	int num2=0;
	char h[110][110];
	int a=0;
	int l;
	while(cin>>h2){
		l=h2.size();
		for(int i=0;i<l;i++)
			h[a][i]=h2[i];
		a++;
	}
	for(int i=0;i<a;i++){
		int n=0;
		for(int j=0;j<l;j++){
			if(h[i][j]=='#')
				n++;
		}
		if(n>num1)
			num1=n;
	}
	for(int j=0;j<l;j++){
		int n=0;
		for(int i=0;i<a;i++){
			if(h[i][j]=='#')
				n++;
		}
		if(n>num2)
			num2=n;	
	}
	if(num1==0&&num2==0)
		cout<<"-1\n";
	else{
		if(num1>num2)
			cout<<num1<<endl;
		else
			cout<<num2<<endl;
	}
	return 0;
} 
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
编译原理是计算专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算科学理论的重要组成部分,也是实现高效、可靠的计算程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算科学理论的重要组成部分,也是实现高效、可靠的计算程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算科学理论的重要组成部分,也是实现高效、可靠的计算程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算科学理论的重要组成部分,也是实现高效、可靠的计算程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

协奏曲❤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值