2022 华东师范大学 数据学院复试机考
本文章参考
xwyzsn作者的《2022 华东师范大学 数据学院复试机考》
2022 华东师范大学 数据学院复试机考_华东师范大学上机考试-CSDN博客
感谢!算法会有不足之处,欢迎大家给予指导,感激不尽!
A.池化
实现一个最大池化操作。
一个filter (题目保证)filter为一个正方形且小于等于 矩阵的边长。即kx==ky<=dx,dy
输入:第一行kx,ky,dx,dy表示filter的长宽,矩阵边长
输出:经过池化操作的矩阵
样例输入:
2 2 3 3
0 1 2
3 4 5
6 7 8
样例输出:
4 5
7 8#include<cstdio> int main() { int at[10][10], kx, ky, dx, dy,max; scanf("%d%d%d%d", &kx, &ky, &dx, &dy); for (int i = 0; i < dx; i++) { for (int a = 0; a < dy; a++) { scanf("%d", &at[i][a]); } } for (int i = 0; i <=dx - kx; i++)//列 { for (int a = 0; a <= dx - kx; a++)//两层for循环实现小矩阵移动 { max = 0; for (int x = i; x <kx+i; x++) { for (int y = a; y<ky+a; y++) {//两层for循环实现矩阵内部大小比较 if (at[x][y] > max) max = at[x][y]; } } printf("%d ", max); } printf("\n"); } return 0; }
B. 去商场
这是一道图的遍历的题目,大致意思为:若其中的坐标为为.则可以随便走,若坐标位置为#有障碍物,不能走。请问小明能不能从家走到商城,若能返回最小的步数。
输入:,m*n 地图(地图中包含 ‘#’,‘.’,‘S’,‘E’)S为起点,E为终点,#表示障碍物,.表示随意同行
输出:到达商城的最小步数,若不能返回-1
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct Node {
int length,i,j;
char a;
bool visited=false;
}p;
int main() {
int m, n;
cin >> m >> n;
int sx, sy;
queue<Node> q;
string a;
vector<vector<Node> >map(m,vector<Node>(n));//构建二维变长数组
for (int i = 0; i < m; i++)
{
cin >> a;
string::iterator it = a.begin();
for (int j = 0; j < n; j++)//输入地图
{
map[i][j].a = *it;
map[i][j].i = i;
map[i][j].j = j;
if (*it == 'S')
{
map[i][j].length = 0;
q.push(map[i][j]);
map[i][j].visited = true;
continue;
}
it++;
}
}
while (!q.empty())//BFS搜索最短路径
{
p = q.front();
if(p.i!=m-1&&map[p.i+1][p.j].a!='#'&&!map[p.i + 1][p.j].visited)
{
map[p.i + 1][p.j].length = p.length + 1;
if(map[p.i + 1][p.j].a=='E')
{
cout << map[p.i + 1][p.j].length;
return 0;
}
q.push(map[p.i + 1][p.j]);
map[p.i + 1][p.j].visited = true;
}
if (p.i != 0 && map[p.i - 1][p.j].a != '#' && !map[p.i -1][p.j].visited)
{
map[p.i - 1][p.j].length = p.length + 1;
if (map[p.i - 1][p.j].a == 'E')
{
cout << map[p.i - 1][p.j].length;
return 0;
}
q.push(map[p.i - 1][p.j]);
map[p.i - 1][p.j].visited = true;
}
if (p.j != 0 && map[p.i ][p.j-1].a != '#' && !map[p.i][p.j-1].visited)
{
map[p.i ][p.j-1].length = p.length + 1;
if (map[p.i][p.j-1].a == 'E')
{
cout << map[p.i ][p.j-1].length;
return 0;
}
q.push(map[p.i ][p.j-1]);
map[p.i][p.j-1].visited = true;
}
if (p.j != n-1 && map[p.i][p.j + 1].a != '#' && !map[p.i][p.j+1].visited)
{
map[p.i][p.j + 1].length = p.length + 1;
if (map[p.i][p.j + 1].a == 'E')
{
cout << map[p.i][p.j + 1].length;
return 0;
}
q.push(map[p.i][p.j + 1]);
map[p.i ][p.j+1].visited = true;
}
q.pop();
}
cout << -1;
return 0;
}
C. 数组变换
题目描述:给定一个数组序列,输出,能不能通过交换 两个相邻数(必须一奇,一偶)而构造出一个会严格递增的序列。
举例:比如[2,1,3]可以交换(1,2)->(1,2,3)可以输出YES,不可以输出NO,如[3,1,2]就没法交换得到,因为必须一奇一偶。
思路:思路大致是,判断奇数序列,和偶数序列,是否递增就可以,因为我们只能交换奇偶,如果因为奇偶我们总能通过交换让她有序。
#include <iostream>
#include<algorithm>
#include <vector>
using namespace std;
int main()
{
vector<int> a;
int n,x;
cin >> n;
bool flag = true;
for (int i = 0; i < n; i++)
{
cin >> x;
a.push_back(x);
}
for (int i = 1; i < n; i++)
{
if (a[i] < a[i - 1] && (a[i] + a[i - 1]) % 2 == 0)
{
cout << "NO";
return 0;
}
if (a[i] < a[i - 1] && (a[i] + a[i - 1]) % 2 != 0 && flag)
{
flag = false;
swap(a[i], a[i - 1]);
}
if(a[i]<a[i-1]&&!flag)
{
cout << "NO";
return 0;
}
}
cout << "YES";
return 0;
}
D. 表情拦截
题目描述:大致为,给定这样一个序列 1,2,3,4,...k,k-1,k-2....1然后给出一个x,若序列的和超过x,后面就会被忽略,输出被截断的位置的行数。
举例:k=3,x=4,[1,2,3,2,1],x=4 那么在第三行就会被截断。
#include <iostream>
#include <cmath>
using namespace std;
int cal(int a) {
return (a*(1+a)) / 2;
}
using namespace std;
int main()
{
int a, k;
cin >> a >> k;
if (a <= cal(k))
{
cout << 1 + (int)(sqrt(1 + 8 * a) - 1) / 2; return 0;
}
else if (a > cal(k) && a < cal(k) + cal(k - 1))
{
int x = cal(k) + cal(k - 1);
int y = 1 + 8 * x - 8 * a;
float t =(- 1 + sqrt(y * 1.0) ) / 2;
if (x == a + cal((int)(-1 + sqrt(y * 1.0)) / 2))
cout << 2*k-(int)t ;
else cout << 2 * k - 1 - (int)t;
}
else cout << "no";
return 0;
}
E .拍照队列
描述:给定一个序列010101其中0表示男生,1表示女生。现在要求任意截取一个子串(length>1)都要满足男生数量不大于女生数量。即010这是合法的0101这是不合法的因为存在010这一个字串不满足。请返回至少要添加几个1满足合法序列。
举例:000->0110110 需要添加四个1
输入:n表示有几个人,s表示一个01的串。输出:最少要添加几个女生
思路:应该要确保两个0之间要有两个1
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<char> str;
string a;
int count = 0,sum=0,j;
cin >> a;
string::iterator it = a.begin();
for (it; it != a.end(); it++)
str.push_back(*it);
for(int i=0;i<str.size()-1;i++)
if (str[i] == '0')
{
count = 0;
j = i + 1;
while (j < str.size()&&str[j] != '0')
{
j++; count++;
if (count == 2)
break;
}
if(count<2)
sum += (2 - count);
}
cout << sum;
return 0;
}
F. 树上的异或和
描述:给定一个树的前序,中序序列,要求你算出根节点的“值”。值的定义如下
叶子节点:值为从根节点到叶子节点的最短路径长度,即边长
非叶子节点
左右孩子都有的:值定义为左右孩子的 异或
只有左孩子的:值定义为左孩子的两倍(做到后面才发现题目没有说他一定是一个满二叉树,所以代码写的都不太对。)
请你返回根节点的“值”
举例:
输入
7(有几个节点)
1 2 4 5 3 6 7(前序),这里的数字只代表这个节点不代表值
4 2 5 1 6 3 7 (中序)
输出:
0
#include <iostream>
using namespace std;
struct Node {
int data,layer=0;
Node* lchild;
Node* rchild;
};
const int maxn = 50;
int pre[maxn], in[maxn];
Node* Btree(int preL,int preR,int inL,int inR,int l) {
if (preL > preR)
return NULL;
Node* p = new Node;
p->data = pre[preL];
p->layer = l;
int k;
for (k = inL; k < inR; k++)
{
if (in[k] == pre[preL])
break;
}
int Lnum = k - inL;
p->lchild = Btree(preL + 1, preL+Lnum, inL, k - 1,l+1);
p->rchild = Btree(preL + Lnum + 1, preR, k + 1, inR,l+1);
return p;
}
int cal(Node* root) {
if (root->lchild == NULL && root->rchild == NULL)
return root->layer;
else if (root->rchild == NULL)
return 2 * cal(root->lchild);
else
return cal(root->lchild) ^ cal(root->rchild);
}
int main()
{
for (int i = 0; i < 7; i++)
cin >> pre[i];
for (int i = 0; i < 7; i++)
cin >> in[i];
Node* root=Btree(0, 6, 0, 6, 0);
int x = cal(root);
cout << x;
return 0;
}