zoukankan      html  css  js  c++  java
  • PAT 1065

    这次的题目来源是 2013 年 10 月 7 日下午的浙大计算机研究生招生机试题。

    这次题目的难度,按姥姥的说法是:『比普通的 PAT 要难了 0.5 个点。我是把自己的题目从 1.0 到 5.0 以 0.5 的间距分难度级别的,PAT(A)难度一般在 1.5-4.5 之间,保研考试一般在 2.0-5.0 之间。PAT(B)大概是 1.0-2.5 的难度。』。

    个人认为,其中 1066 模拟 AVL 插入的实现有些细节容易弄错,而 1068 只要会简单的 DP,也就没有问题了,1065 和 1066 都还是很简单的实现。

    下面是各个题的分析(PAT advanced level 本人实现的全部源码:请戳)。

    1065. A+B and C (64bit) (20)

    题意

    输入三个数 a,b,c,取值范围是 [-2^63, 2^63],要求判断a + b < c 是否为真。

    分析

    很简单的签到题,想到两种方法:一是用 Java 的 Big Decimal 实现(应该不会超时吧-,-),二是对 a+b 造成的 long long 溢出的情况做特殊处理。

    对于分情况的实现方式,实际上也就两种特殊情况,即 a,b 同号且两者之和溢出了(绝对值超过了 263)。此时两者之和与 c 的值的相对关系也是确定的。

    • a < 0 && b < 0 && a + b >= 0: a + b 必小于 c
    • a > 0 && b > 0 && a + b <= 0: a + b 必大于 c

    另在 98 看见有大神说可以用 long double 水过去-,-.

    pat1065 源码:请戳

    1066. Root of AVL Tree (25)

    题意

    实现 AVL 树的插入方法,给定 N(<=20)个数,要求输出依次插入后的 AVL 树的根。

    分析

    由于节点少,可以使用相对简单的递归实现方法:

    • 每个节点维护一个高度值,用在递归插入后检测子树是否平衡
    • 完成 4 个旋转方法(参见 AVL Tree wikipedia 中的示意图)
    • 在递归插入方法中,完成对子树的插入后,检测子树高度差,根据子树的结构特点,做出相应的旋转
    • 旋转后记得更新节点的高度值

    机试时似乎没有人完全 AC 这道题,看来代码实现和 Debug 能力缺乏还是比较普遍的问题。

    pat1066 源码:请戳

    1067. Sort with Swap(0,*) (25)

    题意

    给定 N(<=10^5)以及一个{0,1,…,N-1}的打乱的数列。

    定义了一种交换方式:Swap(0,*),表示将 0 和任意数进行位置交换。

    限定只能使用Swap(0,*),要求输出最少需要多少次交换操作,来完成整体的排序。

    分析

    很好玩的模拟题,从题目的两个测试数据入手,找到所需要的交换次数的特点:

    假设用数组 a 存储输入的数组,数组的坐标为 [0, N - 1],而元素的所有值也是 [0, N - 1]。

    1. 输入的序列中本就在自己位置上的数字,是不用被交换的(比如序列{4, 0, 2, 1, 3}中 2 就是不用被交换),0 除外

    2. 0 最终肯定会被放回到 0 的位置上,但交换过程中,0 也可能被提前交换到了 0 的位置上,此时还有其他数没有处于正确的位置上(参见 Sample Input{10 3 5 7 2 6 4 9 0 8 1}的情况)。此时需要多费一步将 0 和某一个处于不正确位置的数交换位置,来继续排序。

    3. 每次的交换,0 其实只是一个过渡作用。实际的交换过程遵循的链式关系如下所述:设定 a[x] == b, 而 b != x,则需要将 a[x]的值移动到 a[b]上,此时 a[b] == c, 那么接着又需要将 a[b]的值移动到 a[c]上,以此类推,肯定能获得一个循环,且节点数 M 小于等于 N。如果循环中包含了 0,那么这个循环中的数排序所需要的交换次数为 M - 1, 如果循环中不包含 0,那么首先需要一次交换将 0 移动到循环链中,此时整个循环链节点数增加了 1,于是共需要开销 M + 1 次交换。

    4. 根据 3 的分析,在 2 的情况下,0 与不同的不在正确位置的数的交换,是不会影响最终的结果的。

    综上所述,用类似 dfs 或者并查集的思路找到集合中的所有循环链路,记录下他们的大小,即可计算出所需要的交换次数。

    pat1067 源码:请戳

    1068. Find More Coins (30)

    题意

    给定 N(<=10^4) 枚硬币和一个价格 M(<=100)。

    要求用这 N 枚硬币组合出价格 M,如果有多种组合,输出排序后硬币面值字典序最小的组合,如果没有组合,则输出 No Solution.

    分析

    裸背包问题,相关资料参见 dd 大神的总结:《背包问题九讲》

    按照常规的背包思路,构建 10001 * 101 的二维数组 f[i][j],状态 f[i][j] 表示前 i 枚硬币能拼凑出的小于等于 j 的最大值(j 这里代表一个价格)。

    状态转移方程为:f[i][j] = max(f[i - 1][j], f[i - 1][j - c[i]] + c[i]), 其中 c[i]为第 i 枚硬币的面值,c[i]为排序过的硬币面值数组。

    由于最终的输出要求是排序的币值的字典序最小的组合,可以对 c[i]做从大到小的排序,并另开一个数组 has[i][j] 来记录当前状态下,是否有包含 c[i]。同时注意,当f[i - 1][j] == f[i - 1][j - c[i]] + c[i]时,采纳当前的 c[i],以满足字典序。

    pat1068 源码:请戳

  • 相关阅读:
    static&初始化顺序
    java基础语法
    MySQL调优
    Nnginx调优
    cisco 一些基本命令
    路由器密码忘记
    利用GetPrivateProfileString读取配置文件(.ini)
    MFC中OnActivate函数解析
    在MFC应用程序中传输的消息类型
    MFC中UpdateData函数解析
  • 原文地址:https://www.cnblogs.com/biaobiaoqi/p/3357228.html
Copyright © 2011-2022 走看看