SDWC day1 - 非传统题

提答

主要的几种类型:

  • 退火
  • 观察数据规律
  • 手玩
  • 造计算机

模拟退火

退火就是模拟退火。

写的过程中注意下面几点:目标函数,调整对象,答案生产,调整方法。


经典应用:

  • TSP 问题:直接对答案进行退火,每次交换两个位置。
  • 多个背包的背包问题:给每个物品指定一个放置的背包(或不放),按顺序处理每个物品,能放则放,对指定的背包退火。
  • 最大独立集:按一个排列的顺序进行选点,每次考虑选一个点,能选则选,对这个排列进行退火。

例题:CTSC2018 组合数问题

\(n\) 个问题要在 \(k\) 台机器上运行,第 \(i\) 个问题在机器 \(j\) 上运行的时间为 \(a_{ij}\)

这些问题之间有 \(m\) 条依赖关系 \((u,v)\) 表示只有问题 \(u\) 计算完成并将数据发送到问题 \(v\) 所在的机器时才能开始计算问题 \(v\)

两台机器之间传输数据的时间 \(t_{i,j}\)已知

你要安排每个问题在哪台机器上运行,以最小化计算+数据传输的时间之和或整个过程的总时间

直接对每个问题安排在哪台机器上进行退火,每次改变一个任务被安排的机器。zyb 说他写到了 96 /bx


例题:CTS2019 无处安放

若干个举行,把它们不重叠的放在一个大矩形里,求大矩形的最小面积。

对放入矩形的顺序对火,每次放的时候尽可能往左下角堆(这个“尽可能往左下角”可以形式化的写成对每个位置求一个估价函数,找到估价最高的地方)(估价函数怎么求?待填坑)

可以枚举大矩形,退火的目标射程最小化宽。

不是很懂。

据说能搞到 80pts,然后仔细实现+一些测试点人眼找规律就可以切掉。

观察数据规律

直接瞪眼观察

先猜出题人可能会造什么样的特殊数据,然后写个程序验证一下。

比如一张 \(100\) 个点 \(180\) 条边的图就很有可能是一张正方形网格图。(WC2019远古计算机)

手玩

出题人直接出个游戏让你手玩,比如魔塔

正经一点的一般是在看出测试点性质之后进行手动构造。

比如WC2019远古计算机的最后一个点,看出这是个网格图之后构造依然挺复杂。

造计算机题

一般会给你一种计算节点的模型(存储的数据类型以及支持的运算),你要搭建一个计算的体系来完成相应的计算任务。

例题: NOI2016 旷野大计算,WC2019远古计算机,IOI2021 位移寄存器

简单总结造计算机题的思路:

  • 先看模型。给的计算节点是什么,运算是什么拿些特性(比如相比常规的几种运算多了什么,少了什么)是可以被利用的。
  • 再看求解目标。把求解目标尽可能拆分成基本运算。
  • 确定给定的运算中哪些是需要的,那些是凑数的。
  • 第二步中,如果你拆出来的基本运算没有给定怎么办?想办法利用已有的运算性质凑出来。
  • 有时候需设计算法
  • 找测试点前后之间的关联,也许前面一个实现的东西在后面可以很方便的用到。

交互

一般就是我们需要实现一个函数,这个函数直接传入的参数很少,其余获得的信息都是你想交互库询问得到的(通过调用一个询问函数来实现)

询问通常有次数上线,或者说希望你尽可能少地询问并以询问次数作为评分标准。

除此之外,有的题目可能有一些非常奇怪的题目要求需要用交互来实现(最简单的,可以用交互来实现强制在线)

大体分一下:

  • 询问次数要求 \(100\) 次一下的:一般是一些奇妙的二分技巧。有可能精确的卡次数(IOI2018高速公路收费)或者比较恶心的分类讨论(有几个这样的 CF 题)
  • 询问次数 \(O(n)\) 的一般会有很神仙的脑洞,这个 \(O(n)\) 很有可能是从暴力的 \(O(n^2)\) 甚至 \(O(n \log n)\) 优化下来的(WC2019 i君的商店)
  • 询问次数更多,有可能卡算法,更像一道传统题。(WC2018 即使战略)

通信

一般来说你需要些两个程序(有的丧心病狂的题可能要写多个),然后首先执行程序 \(A\) ,得到一些输出;然后输出经过处理后会输入到程序 \(B\),要求程序 \(B\) 完成一些任务。

程序 \(A\)\(B\) 之间一般不能通过其他方式(比如共享全局变量)交流。

最简单的类别:程序 \(A\) 得到一些(以某种格式的)输入,需要按照某种格式输出;程序 \(B\) 直接输入程序 \(A\) 输出的内容,需要还原出程序 \(A\) 输入的内容。

一个最简单的例子:

程序 \(A\) 输入一个长度为 \(n\) 的排列,输出一个 long long 范围内的正整数;程序 \(B\) 输入这个正整数,输出程序 \(A\) 输入的排列是什么。\(n \le 20\)

康托展开和逆康托展开。


这种题的共性是:输入数据的种类数都比输出数据的种类数小,而且输入数据可以很方便地与输出数据的一个子集建立一一对应关系(变换的规律很直接,而且正变换和逆变换都很好实现)。

这种是最简单的。

复杂一点的类型,可能很难去准确计算出输入数据的种类数到底有多找。

可能会让你把输入数据压缩成 01 串,然后评分标准是 01 串的长度。

说白了,我们的任务就是去实现一个数据的无损压缩,直接掏出我祖传的 winrar !

与前一个题的不同之处在于,对应的规则可能很复杂。

还有一种与之相反的类型,程序 \(A\) 输入一个数,需要输出一个奇怪的东西;程序 \(B\) 输入这个奇怪的东西之后还原出程序 \(A\) 的数。

同样的,这个“奇怪的东西”的种类数虽然可能比数的范围大得多,但是很难建立于数之间一一对应关系。

更复杂的通信提就不仅仅是数据的无损压缩这么简单了。

比如,实现数据的有损压缩,使得程序 \(B\) 只需要提取一些有用的信息

有一个例子是程序 \(A\) 输入一张边权为 \(1\) 的图和一些关键点,输出一个 \(01\) 串,程序 \(B\) 需要解压出这些关键点的两两距离。(没讲做法)

再比如,程序 \(A\) 的输出受到一些程序 \(B\) 不知道的限制。

还有很多其他模型,比如程序 \(B\) 需要与交互库实现一些交互任务,而程序 \(A\) 的输出是为了给交互库提供参数。

还有的通信题需要一些算法知识(和更多的脑洞)

鸣谢

感谢 zyb 的讲解和课件。

posted @ 2022-02-16 17:25  Suzt_ilymtics  阅读(106)  评论(0编辑  收藏  举报