2019北邮计算机机试回忆和前三道题题解

今年北邮机试不让带资料了,预计今后都不会再让带资料,影响还是蛮大的。

Problem A 二进制

题目

32位二进制数X,输出X+1和X+3之后的32位二进制数

输入

第一行输入一个整数T,代表测试数据组数。
接下来的T行,每行输入一个32位二进制数

输出

对每组测试数据,输出两行,第一行为X+1,第二行为X+3

测试用例

输入

2
00000000000000000000000000000000
00000000000000000000000000000001

输出

00000000000000000000000000000001
00000000000000000000000000000011
00000000000000000000000000000010
00000000000000000000000000000100

思路

笨比做法,把32位二进制数转化为十进制数再转化为二进制数,注意转化成的十进制数要用long long

代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		char str[33];
		scanf("%s",str);
		long long num=0;
		int l=1;
		for(int i=31;i>=0;i--)
		{
			num+=(l*(str[i]-'0'));
			l*=2;
		}
		long long num1=num+1;
		int ans1[32];
		int size1=0;
		while(num1>0)
		{
			ans1[size1++]=num1%2;
			num1/=2;
		}
		for(int i=31;i>=size1;i--)
			printf("0");
		for(int i=size1-1;i>=0;i--)
			printf("%d",ans1[i]);
		printf("\n");
		long long num2=num+3;
		int ans2[32];
		int size2=0;
		while(num2>0)
		{
			ans2[size2++]=num2%2;
			num2/=2;
		}
		for(int i=31;i>=size2;i--)
			printf("0");
		for(int i=size2-1;i>=0;i--)
			printf("%d",ans2[i]);
		printf("\n");
	}
	return 0;	
} 

Problem B 二叉树

题目

计算二叉树两个结点的最短距离。

输入

第一行输入测试数据组数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

思路

其实这道题应该找二叉树的公共祖先。但是机试的时候,一方面是我之前没有写过二叉树公共祖先,一方面是懒,直接把二叉树转化成了父节点和子节点距离为1的图,然后dijkstra算了一下最短路径

代码

#include<bits/stdc++.h>
using namespace std;
const int N=100;
const int inf=1e10+10;
vector<int>edge[N],cost[N];
struct Node
{
	int v,w;
	Node(){}
    Node(int v,int w):v(v),w(w){}
	bool operator <(const Node &A)const
	{
		return w>A.w;
	}
};
int dist[N];
bool vis[N];
void dijkstra(int start)
{
	for(int i=1;i<=N;i++) dist[i]=inf,vis[i]=0;
	dist[start]=0;	
	priority_queue <Node> Q;
	Q.push(Node(start,0));
	while(!Q.empty())
	{
		Node tmp=Q.top();Q.pop();
		int u=tmp.v;
		if(vis[u])	continue;
		vis[u]=1;
		for(int i=0;i<edge[u].size();i++)
		{
			int v=edge[u][i],w=cost[u][i];
			if(dist[v]>dist[u]+w)
			{
				dist[v]=dist[u]+w;
				Q.push(Node(v,dist[v]));	
			}	
		}	
	} 
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n,m;
		while(scanf("%d%d",&n,&m)!=EOF)
		{
			for(int i=1;i<=n;i++) edge[i].clear(),cost[i].clear();
			for(int i=1;i<=n;i++)
			{
				int u,v;
				scanf("%d%d",&u,&v);
				if(u!=-1)
				{
					edge[i].push_back(u);
					cost[i].push_back(1);
					edge[u].push_back(i);
					cost[u].push_back(1);
				}
				if(v!=-1)
				{
					edge[i].push_back(v);
					cost[i].push_back(1);
					edge[v].push_back(i);
					cost[v].push_back(1);
				}
			}
			for(int i=1;i<=m;i++)
			{
				int str,end;
				scanf("%d%d",&str,&end);
				dijkstra(str);
				printf("%d\n",dist[end]);
			}
		}
	}
	return 0;
}

Problem C 最短路径

题目

计算从城市1到城市n的最短路径长度。分为白天和黑夜,黑夜会关掉若干条线路,分别计算城市1到城市n的在白天和黑夜的最短路径长度。保证每个城市与其他城市必有连接。两个城市之间可能有多重边

输入

第一行输入T,测试用例组数
第二行输入n,m,k. n是城市数,m是边数,k是黑夜关闭的边数(n<=50)
接下来m行,每行输入三个数x,y,z,代表城市x和城市y之间的距离
最后一行k个数,代表晚上关闭的线路序号

输出

每组数据输出两行,分别代表白天和黑夜,城市1到n的最短路径长度

测试用例

输入

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

输出

1
3

思路

上来一读题,读到节点数小于等于50,马上写了个Floyd,用例跑过之后,提交,结果发现oj多了提醒:可能会有重边。遂改成dijkstra,用vector建图,本来想的是建好了图之后,把黑夜中要关闭的边从vector中erase掉就ok,奈何基础还是比较差,erase之前也用的比较少,本地error都解决不了。改了思路,把输入的边存一下,在计算黑夜的最短路径的时候重新建图,不把黑夜中要关闭的边加进去。幸好这题测试数据规模小,笨比做法也能搞定。119分钟提交的第3题,最后一分钟过了,心情着实经历了一番大起大落。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=100;
const int inf=1e10+10;
vector<int>edge[N],cost[N];
struct Node
{
	int v,w;
	Node(){}
    Node(int v,int w):v(v),w(w){}
	bool operator <(const Node &A)const
	{
		return w>A.w;
	}
};
struct road
{
	int u,v,w;
};
int dist[N];
bool vis[N];
void dijkstra(int start)
{
	for(int i=1;i<=N;i++) dist[i]=inf,vis[i]=0;
	dist[start]=0;	
	priority_queue <Node> Q;
	Q.push(Node(start,0));
	while(!Q.empty())
	{
		Node tmp=Q.top();Q.pop();
		int u=tmp.v;
		if(vis[u])	continue;
		vis[u]=1;
		for(int i=0;i<edge[u].size();i++)
		{
			int v=edge[u][i],w=cost[u][i];
			if(dist[v]>dist[u]+w)
			{
				dist[v]=dist[u]+w;
				Q.push(Node(v,dist[v]));	
			}	
		}	
	} 
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n,m,k;
		scanf("%d%d%d",&n,&m,&k);
		for(int i=1;i<=n;i++) edge[i].clear(),cost[i].clear();
		road tmp[101];
		for(int i=1;i<=m;i++)
		{
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			tmp[i].u=u;tmp[i].v=v;tmp[i].w=w;
			edge[u].push_back(v);
			cost[u].push_back(w);
			edge[v].push_back(u);
			cost[v].push_back(w);
		}
		dijkstra(1);
		printf("%d\n",dist[n]);
		
		for(int i=1;i<=n;i++) edge[i].clear(),cost[i].clear();
		int clo[101];
		for(int i=1;i<=k;i++)
			scanf("%d",&clo[i]);
		for(int i=1;i<=m;i++)
		{
			bool flag=false;
			for(int j=1;j<=k;j++)
			{
				if(i==clo[j]) 
				{
					flag=true;
					break;
				}
			}
			if(flag==false)
			{
				int u,v,w;
				u=tmp[i].u;v=tmp[i].v;w=tmp[i].w;
				edge[u].push_back(v);
				cost[u].push_back(w);
				edge[v].push_back(u);
				cost[v].push_back(w);
			}			
		}
		dijkstra(1);
		printf("%d\n",dist[n]);
	}
	return 0;
}

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值