• noip2008提高组题解


    第一题:笨小猴

    模拟

     

    第二题:火柴棒等式

    搜索

    深搜不用说,确定出两个加数然后判断能否拼出等式。

    枚举确实不太好搞,因为枚举范围不确定,太大了容易超时,太小了容易漏解。不过这题的数据貌似很温和,我从 0~1000 枚举也能过。

     

    第三题:传纸条

    多线程动态规划

    跟 2000 年的方格取数很像。

    还是看做两个人同时从左上角走到右下角。用 f(i, j, k) 表示横纵坐标和为 i,第一个人的行坐标为 j,第二个人的行坐标为 k 时的最大和。

    由于一个地方不能走两次,所以对于除了终点以外的所有 j = k 的情况,其 f 值应等于负无穷。(j=k && i!=m+n && j!=m 才是终点的情况)

     

    第四题:双栈排序

    二分图判定

    首先想到的是贪心,能拿 30~50 分左右。

    然后看了下题解。(参考 https://www.byvoid.com/blog/noip2008-twostack/http://www.cnblogs.com/vb4896/p/3875833.html

    首先我们要判断一个序列能否进行双栈排序。两个栈,容易让人想到二分图。按照这个思路往下想,二分图中的边所代表的关系很明显是指两个数字不能进同一个栈。那么如何判断两个数字能否进同一个栈?

    对于任意的数对 (i, j) 满足i<j且a[i] < a[j],若存在 k 使得 k > j > i 且 a[k] < a[i] < a[j],则 i 和 j 必然不能进入同一个栈。(简单解释一下:因为 k 在 i 和 j 的后面,所以在 k 出栈之前 i 和 j 都在栈内,如果 i 和 j 在同一个栈内,j 必然比 i 后入栈,也必然比 i 先出栈,这样就违背了应有的顺序,所以 i 和 j 不能在同一个栈内)

    那么我们只需对于满足上述条件的数对 (i, j) 连一条边,最后染色判断是不是一个二分图即可。

    判断数对 (i, j) 是否满足条件,如果用朴素的算法,时间复杂度将是 O(n)。我们每次判断的过程事实上是判断在 j 后面的数字中能否找到一个小于 a[i] 的数字。那么我们只需知道 a[j+1]...a[n] 中的最小值即可。用 f[i] 表示 a[i]...a[n] 中的最小值,则 f[i] = min{ f[i+1], a[i] }。每次对于 (i, j) 只要判断 f[j+1] 是否小于 a[i] 即可。复杂度 O(1)。

    由于我们要得到字典序最小的方案,那么很明显应该尽量将顺序靠前的数字安排在栈 1 中。

    如果得到的是二分图,进行贪心即可。每次如果可以进行多种操作,选择字典序最小的操作。

    (顺便一提,BYVoid 大神的代码是有问题的,可以参加那篇文章下面的第一条评论。)

  • 相关阅读:
    void*指针的由来
    Linux下的ELF文件格式简介
    通过中断门或陷阱门的转移——【只上传好图一张】
    ELF(Executable and Linking Format)
    call Init8259A——痛定思痛,不要数典忘祖了
    orange's习题——第三章【中断和异常】
    静态库
    可执行文件elf的格式
    谈谈我对攻读计算机研究生的看法
    tips for C
  • 原文地址:https://www.cnblogs.com/lsdsjy/p/3945806.html
Copyright © 2020-2023  润新知