南京大学计算机考研机试,2018南大CS考研机试答案

Problem A

第一题最笨的思路(by:LittleSec)

都规定输入的最大深度是5了,所以直接穷举深度为1-5的满二叉树前序->中序方案,主要就是下标转换:

eg:输入ABC对应的下标是012,输出是顺序变成102而已。

eg:高度为3的情况则构造下标数组:a[] = {2,1,3,0,5,4,6},假设输入的字符串存在str,那么输出就是

for(int i = 0; i < pow(2,n)-1; i++)

{

if(str[a[i]]=='#') continue;

else cout << str[a[i]];

}

5种情况而已,草稿纸上列举不用10分钟。

亲测能通过所有测试样例。(:逃

第一题稍微不那么笨但还是很笨的思路(by:六月雪Yuni)

只要知道如何从满二叉树的先序遍历推出原树就可以做。根据定义,满二叉树的某一棵子树的先序遍历是[根][左子树序列][右子树序列]的形式,而且左子树序列和右子树序列长度相同。那么先取出根,然后递归处理左子树和右子树就可以构造出原树。得到原树之后中序遍历乱搞就可以啦。

另外值得注意的是有一些原本可以得到300分的大佬因为读题失误,把#节点认为是不存在的节点,而忽略了#节点也可能作为父节点的情况,导致本题只能做到80分或90分。呜呼哀哉————读题果然也是重要的一环呢。

这个思路得到了AC(100pts)。

伪代码:

void ConstructTree(int l, int r){

root = s[l];

root.leftChild = s[l+1];

root.rightChild = s[l+1+(r-l)/2];

ConstructTree(l+1,l+(r-l)/2);

ConstructTree(l+(r-l)/2+1,r);

}

void Output(int root){

Output(root.leftChild);

print(root);

Output(root.rightChild);

}

Problem B

第二题菜鸡拿分经验贴(by:还是最笨的LittleSec

题中给定输入是s t,千万认为s一定比t小。当s比t大的话,也就是农夫在牛的后面,那么农夫每次都只能执行后退即-1操作,因此最短步数就是s-t步。亲测能通过4个测试样例(噗

第二题思路1 广度优先搜索(by:六月雪Yuni)

直接从点s开始BFS。用一个数组vis[]维护元素x是否被加入过队列,d[]记录扩展到元素x需要搜索几步。

每次取出队首元素fr时,测试fr+1是否在队中,不在则加入队列,并且更新d[fr+1]。对fr-1和fr*2同样这么做。

需要注意的是加入队列的元素不能是负数,因为0<=s,t<=100000,加入负数没有意义。fr*2也不能超过100000。

这个思路做到了AC(100pts)。

部分代码:

int BFS(int s, int t){

memset(d,0x3f,sizeof(d)); //这一步将d中所有元素初始化为一个“无限大”,即在题目语境里非常大的数

const int inf = 0x3f3f3f3f;

d[s] = 0;

queue Q;

while(!Q.empty())Q.pop();

Q.push(s);

while(!Q.empty()){

int fr = Q.front();

if(fr-1>=0 && d[fr-1]>=inf){

Q.push(fr-1);

d[fr-1] = d[fr] + 1;

}

if(d[fr+1]>=inf){

Q.push(fr+1);

d[fr+1] = d[fr] + 1;

}

if(fr*2<=100000 && d[fr*2]>=inf){

Q.push(fr*2);

d[fr*2] = d[fr] + 1;

}

Q.pop(fr);

}

return d[t];//因为我们知道本题一定有解,所以不判定是否存在。

}

第二题思路3 DP

听说有大佬用动态规划解了这题,待补充。

Problem C

第三题思路1 DP(by 笔试爆炸啦qaq)

我们令dp[i][j]为串s[1..i]和t[1..j]的最长公共子序列长度。例如,对s="abcde"和t="acefg",s[1..4]="abcd",t[1..3]="ace",所以dp[4][3]=2。(最长公共子序列是"ac")

这样,就有了以下的递推式:

s[i] == t[j] : dp[i][j] = max(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]+1).

s[i] != t[j] : dp[i][j] = max(dp[i-1][j], dp[i][j-1]).

初始条件 dp[0][0] = 0

时间复杂度O(L^2),L = max(s.length, t.length).

然后dp[s.length][t.length]就是串s和串t的公共子序列长度。将这个过程重复n次、取最大就可以求得题目的解。因为1<=n<=200,L<=2000,所以可以在时限内得到解。

这个思路得到了AC(100pts)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值