背景
南京大学计算机系暨人工智能学院的开放日分两场,时间大概在七月中旬和七月下旬。其中南京本地的学生参加七月中旬的,外地学生参加七月下旬的。两次开放日上机考试的题目不同,难度也不同,按照以往的惯例都是本地生简单一些。我发现网上开放日,九推相关的信息和资料都很有限。
所以
我来总结一下2019年的开放日和九月推免。
开放日Ⅰ
首先是外地生的开放日(夏令营)开放日分两部分,一般是上午面试,下午上机考试,各占300分,加起来算总分。面试是三个老师(面试过程录像)会跟据你的简历和成绩单提问题,最后会有一个英文问题,大多是以后的科研规划或者你觉得学得最好的一门课。面试不会太为难你,大方自信一些就行。
下午的上机考试是重点,因为上机的成绩好坏与最后是否录取有直接联系。上机考试有三道全英文的算法题,语言要求用C/C++/Java。每道题有十个样例,每过一个样例得十分。代码先在编程软件(VS/Dev C++)上调试,调完了上交到系统评分,到时候会有解题和提交手册来教你怎么写格式和如何提交。总体来说运行很快,提交后很快就会得到反馈分数。下面直接上题:
Ⅰ.Find the Smallest Number
Description
Given a non-negative integer number n, which could be represented by a sequence of t digits as in its decimal form, you are supposed to remove k digits from the sequence so that the new number is the smallest among all possibilities. If all digits are removed, the result is 0.

Input
The input contains two lines. The first line is a non-negative t-digit integer n, and the second line is the non-negative integer k.
0≤n<101000 \leq n < 10^{100}0≤n<10
100

0<t≤1000 < t \leq 1000<t≤100
0<k≤t0 < k \leq t0<k≤t

Output
The output contains one line with a single integer, which is the smallest number obtained by removing k digits from n.

Sample Input1
  12
  1
Sample Output1
  1
Sample Input2
  12319
  3
Sample Output2
  11
翻译一下:给你一个不超过100位的数n,和一个不超过100的数字k,要求从数n中去掉k个数字,然后使得去掉k个数之后,n最小。
很简单的题目,可以dp但没必要,最常见的解法应该用贪心算法,用栈也可以。贪心策略为:每一步总是选择一个使剩下的数最小的数字删去,即按高位到低位的顺序搜索,若各位数字递增,则删除最后一个数字,否则删除第一个递减区间的首字符。然后回到串首,按上述规则再删除下一个数字。重复以上过程k次,剩下的数字串便是问题的解了。题解:https://blog.csdn.net/C20190413/article/details/77368590

#include<iostream>
using namespace std;
int k;
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		string n; //定义字符串n
		cin>>n>>k;
		int len=n.size(); //也可以用n.length()来取字符串n的长度
		while(k--)
			for(int i=0;i<len;i++) //枚举
				if(n[i]>n[i+1]||i==len-1) //删除遇到的第一个递减序列的第一个数字(若整个字符串为非递减序列,则删去末尾的数字)
				{
					n.erase(i,1); //把当前字符从字符串中删除
					break; //不可省略,否则字符串会多删字符
				}
		while(n[0]=='0'&&n[1]) //去掉前缀0,并至少保留1个数字
			n.erase(0,1); //删去当前字符串开头的'0'
		cout<<n<<endl; //输出字符串
	}
	return 0;
}

Ⅱ.Line up
Description
The teacher is trying to line up B boys and G girls to have a “quiet” queue of students: if there are more than K boys standing consecutively in the queue, the queue is not “quiet”. Please help the teacher to figure out how many ways are there to arrange a “quiet” queue?
Note that we do not consider the order of different students with the same gender. For example, in the case below, Q1 and Q2 are considered as the same arrangement.
  Q1: Girl1, Girl2, Boy1, Boy2
  Q2: Girl2, Girl1, Boy2, Boy1

Input
The input contains one line with three integers B, G and K, separated by a single space.

Output
The output contains one line with a single integer W: the number of the ways to arrange a “quiet” queue mod 10007.
  1≤B≤1001 \leq B \leq 1001≤B≤100
  1≤G≤1001 \leq G \leq 1001≤G≤100
  1≤K≤1001 \leq K \leq 1001≤K≤100

Sample input
  3 1 2
Sample output
  2
翻译一下:有B个男孩,G个女孩,要求所有男孩女孩排成一队,连续的男孩个数不可以超过K个,问一共有多少种排法。
很明显的dp,也可以用dfs,但dfs拿不到满分。
动态规划的思路:
dp[i][j][k] 已安排i个男生,j个女生,并且以k个男生作为结尾。
转移方程:
当i > 0 && k > 0时.dp[i][j][k] += dp[i-1][j][k-1]
当j > 0时.dp[i][j][0] += dp[i][j-1][k]

#include <cstdio>
#include <iostream>
#define ll long long
using namespace std;
const int maxn = 100+5;
const int maxk = 100+5;
const int MOD = 10007; 
ll dp[maxn][maxn][maxk];
int main(){
	int B, G, K; cin >> B >> G >> K;
	dp[1][0][1] = 1; dp[0][1][0] = 1;
	for(int i = 0; i <= B; i++){
		for(int j = 0; j <= G; j++){
			for(int k = 0; k <= K; k++){
				if(i > 0 && k > 0)
					dp[i][j][k] = (dp[i][j][k]+dp[i-1][j][k-1])%MOD;
				if(j > 0)
					dp[i][j][0] = (dp[i][j][0]+dp[i][j-1][k])%MOD;
			}
		}
	}
	ll ans = 0;
	for(int i = 0; i <= K; i++){
		ans = (ans+dp[B][G][i])%MOD;
	}
	cout << ans << endl; 
	return 0;
}

Ⅲ. The Number of Binary Tree
Description
We are all familiar with the pre-order, in-order, and post-order traversal of binary trees. Given the pre-order and the in-order traversal of a binary tree, the post-order traversal could be computed. It is also possible to find the pre-order traversal, given the post-order and the in-order traversals of a binary tree. However, given the pre-order and post-order of a binary tree, you cannot determine the in-order traversal sequence.
Now, given the pre-order traversal and the post-order traversal of the same binary tree, you are supposed to figure out the number of all possible binary trees.

Input
The input contains 2 lines. The first line gives the pre-order traversal of the tree(s), and the second line gives the post-order traversal of the tree(s). The input character set is {a-z} and the length is no more than 26.

Output
The output contains one line with an integer: the total number of possible binary trees.

Sample input
  abc
  cba
Sample output
  4
翻译一下:给出一个二叉树的前序遍历序列和后序遍历序列的字符串,问通过这两个序列可以构造多少中不同的二叉树?
很明显的dfs,暴力直接过,话不多说直接上代码。

#include <iostream>
#include <string>
using namespace std;
string pre, pos;
int cal(string pre, string pos){
	if(pre.size() == 0 && pos.size() == 0) return 1;
	if(pre.size() != pos.size()) return 0;
	if(pre[0] != pos[pos.size()-1]) return 0;
	if(pre.size() == 1 && pos.size() == 1) return 1;
	int ans = 0;
	for(int i = 0; i <= pre.size()-1; i++){
		ans += cal(pre.substr(1, i), pos.substr(0, i)) 
			* cal(pre.substr(i+1, pre.size()-i-1), pos.substr(i, pos.size()-i-1)); 
	}
	return ans;
}
int main(){
	cin >> pre >> pos;
	cout << cal(pre, pos) << endl;
	return 0;
} 

以上就是外地组的三道上机题目,可以看出来并不是很难。在做上机的时候不要在一道题上死磕,学会放弃,合理的时间分配会帮助你取得更高的分数。
开放日Ⅱ
本地组没有很详细的题目,可以参考下。
https://blog.csdn.net/hizcard/article/details/95601101
与外地组相比在难度上没有什么本质区别,都需要稳定扎实的基本功。可以发现dpdfs是几乎必考的。
九月推免
九推和开放日流程基本一样,但从2019年开始人工智能学院与计科的面试分开进行,形式还是一样的。上机考试还是在同一间机房里,题目也是一样的,但难度相比开放日来说激增,三道题每道题都很长,光翻译完理解题意都要快十分钟。
Ⅰ.题目太长,快两页纸,记不住。很无语的题目,要分十几种情况讨论,十分考验同学的耐心和写代码的基本功,如果真正按要求写完,估计要一个半小时,还很有可能拿不到满分。不推荐在考试的时候投入太多的时间。
Ⅱ.happy string
一道令人”happy“的题目。
翻译一下:输入是两行,第一行是一个字符串,由一定数量的’s’,‘a’,'d’三个字母组成,第二行是一个和字符串等长的数组,数组的每个值对应字符串相应位置字符的权值。要执行的操作就是从字符串中删除几个字符,使删除后的字符串不包含’sad’这个子序列,并且要使删去的几个字符的权值和最小。
样例:input:saad
10,1,2,20
output:3
删去‘aa’ 对应权值和为3,满足题意
dp可以做,或者dfs暴力求解,但我做不出来。
Ⅲ.拯救公主
剧情很繁琐,恶龙抓住了公主,骑士推炸弹去救公主(……)
其实,就是一个推行箱子游戏。
就是在一个NM的地图上,有1个玩家、1个箱子、1个目的地以及若干障碍,其余是空地。玩家可以往上下左右4个方向移动,但是不能移动出地图或者移动到障碍里去。如果往这个方向移动推到了箱子,箱子也会按这个方向移动一格,当然,箱子也不能被推出地图或推到障碍里。当箱子被推到目的地以后,游戏目标达成。现在告诉你游戏开始是初始的地图布局,请你求出玩家最少需要移动多少步才能够将游戏目标达成。 https://blog.csdn.net/zuochao_2013/article/details/78269734
输入:4 4

@

.X…
输出:3

输入:6 6
…#…

#*##…
…##.#
…X…
.@#…
输出:11

输入:3 6
.X#…@
.#.*…

输出:11

代码:

#include<iostream>  
#include<queue>  
#include<string>  
using namespace std;
int state[10][10][10][10];//四维数组表示人和箱子的位置状态,开始全为0  
 
struct q
{
	int px, py, bx, by;
	q(int x, int y, int bx, int by) :px(x), py(y), bx(bx), by(by) {}
};
int moves[4][2] = { { 0,1 },{ 0,-1 },{ -1,0 },{ 1,0 } };//四个方向  
char map[10][10];//地图数组  
int chx, chy, cbx, cby, ex, ey, n, m;//分别表示当前人的位置,盒子的位置,终点位置,以及地图尺寸。  
 
bool bound(int x, int y)//边界检查,遇到不合理的位置返回真  
{
	if (x < 0 || y < 0 || x >= n || y >= m || map[x][y] == '#')
		return true;
	else
		return false;
}
//广度优先算法
int bfs()
{
	state[chx][chy][cbx][cby] = 1;//当前其实状态位置设步数为1  
	q temp(chx, chy, cbx, cby);
	queue<q> que; //状态队列  
	que.push(temp);//初始状态入栈  
	while (que.size()) //只要队列不为空就一直寻找  
	{
		temp = que.front();//获取首元素  
		que.pop();//首元素弹出  
		if (temp.bx == ex&&temp.by == ey)
			return state[temp.px][temp.py][temp.bx][temp.by] - 1;//如果箱子在终点,结束,返回步数  
		for (int i = 0; i < 4; i++)//四个方向开始搜索了  
		{
			//先更新人的位置  
			int px = temp.px + moves[i][0];
			int py = temp.py + moves[i][1];
			if (bound(px, py))
				continue;//如果这个位置非法,探寻其它方向  
			if (px == temp.bx&&py == temp.by)//如果此时人的位置与箱子的位置重合,说明人应当推动了箱子  
			{
				if (bound(temp.bx + moves[i][0], temp.by + moves[i][1]))
					continue;//如果箱子移动的位置不合法,则重新探寻其它方向  
				state[px][py][temp.bx + moves[i][0]][temp.by + moves[i][1]] =
					state[temp.px][temp.py][temp.bx][temp.by] + 1;//箱子推动,则人和箱子位置改变,记录新状态  
				que.push(q(px, py, temp.bx + moves[i][0], temp.by + moves[i][1]));//新状态入栈  
 
			}
			else//人没有推动箱子  
			{
				if (state[px][py][temp.bx][temp.by])//如果移动后的状态出现过,则重新搜索新方向  
					continue;
				state[px][py][temp.bx][temp.by] = state[temp.px][temp.py][temp.bx][temp.by] + 1;
				//没有走过这条路就走着试试  
				que.push(q(px, py, temp.bx, temp.by));//更新状态  
 
 
			}
 
		}
	}
	return -1;//如果所有位置都试过了,没有找到,说明不存在  
 
}
 
 
int main()
{
	cin >> n >> m;
	//cin.clear();  
	for (int i = 0; i < n; i++) {
		scanf_s("%s", map[i], m + 1);
	}
	for (int i = 0; i < n; i++)//初始化人,箱子,终点的位置  
	{
		for (int j = 0; j < m; j++)
		{
			if (map[i][j] == '*')
			{
				cbx = i;
				cby = j;
			}
			else if (map[i][j] == 'X') {
				chx = i;
				chy = j;
			}
			else if (map[i][j] == '@')
			{
				ex = i;
				ey = j;
			}
		}
	}
	cout << bfs() << endl;
	system("pause");
	return 0;
}

这次九推的题目是很难的,两个小时能做出一道全对就已经十分了不起。做题的策略很重要,基本功和耐心也是必须的要素。
2018年的题:https://blog.csdn.net/climber16/article/details/81604342

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐