某一天当我还是个萌新,在东北玩泥巴雕塑园看着攻略连馒头的时候,突然
于是我陷入了深深的撕烤,哦不,思考【然后就把这事儿给鸽了,对方可是蓝莓啊喂
@Amastacia大佬我错了
--------------------------------------------鱼唇的分割线--------------------------------------------
我要讲啥来着、、、哦利用动态规划解决问题
具体是什么问题呢:造竹笋by 这位蓝莓
本人画图可好啦!于是画了个二重竹笋卖个萌
显然对于竹笋,给出一个图案,一定是能按照一定顺序连出来的,因此顺序并不重要
重要的是,怎么连【凑字数的废话
好,先来看一个naive的问题:n重竹笋要多少个portal?
$CNT[n] = 3 + 3^{0} + 3 ^{1} + ... + 3^{n-2} = \frac{3^{n} - 1}{2} + 3$
然后蓝莓的要求是
也就是$CNT = 124$个点。。。
$O(n^4)$的算法差不多能满足要求
--------------------------------------------更鱼唇的分割线--------------------------------------------
以下为技【cou】术【zi】部分:
$Sol 1.$
假设每个portal的坐标已经确定,不妨先设刚好有$n = 124$个点,且能够组成一个六重竹笋
令$f[i][j][k]$表示以$i、j、k$三点为外点的竹笋的最多重数,则易知转移方程
$f[i][j][k] = max_{p \in \Delta ijk}\{min(f[i][j][p], f[i][p][k], f[p][j][k])\} + 1$
其中$f[i][j][p]$等三项一定是$f[i][j][k]$的子问题,因此只要记忆化搜索就能解决
时间复杂度$O(n^4)$,空间复杂度$O(n^3)$
评价:好像并没有什么卵用,五重应该还能用上来凑凑数
$Sol 2.$
介于@Amastacia自己的行动四层蓝竹笋已经覆盖了大半个北航校园可知无用点应当相当多,因此需要一个比较简单却高效的剪枝
$Step 1.$首先计算每个三角形内有多少po:
令$g[i][j][k]$表示以$i、j、k$三点为外点的三角形里面包含多少portal
每次选出两点$i、j$,查看其一边的点集$\{S\}$,距离从小到大排序
因此对于每个点$k$,之前的任意点$p$距离$i、j$都比它近,即
$p \in \Delta ijk \ \Leftrightarrow \ \alpha_1 < \alpha_2 \ \&\&\ \beta_1 < \beta_2$
这就可以转化成一个简单的二维坐标系某个点左下方有几个点的问题,时间复杂度$O(nlogn)$
综上,$g[i][j][k]$可以在$O(n^3logn)$的时间内求出
$Step 2.$接下来就可以瞎搞了
本着勤俭持家的原则:对于一个$g[i][j][k] \in [CNT[x], CNT[x + 1]]$
我们期望他的$f[i][j][k] = x$
因此可以对$g[i][j][k]$分类,每一类的$f$值都只与上一类有关
$n=1$时,十分trivial
$n=2$时,即所有$g[i][j][k] == 1$的$i、j、k$满足要求
$n=3$时,内部点并不多,时间复杂度为$O(13 * n^3)$
$n=4$时,内部点依旧不多,时间复杂度为$O(40* n^3)$
$n=5$时,我实在是想不出来了。。。让我们愉快的压常数吧!
$n=6$时,满足$g[i][j][k] \geqslant 121$的组合显然不多,可以期望复杂度在$O(121 * n^2)$【我猜的】
$Step 3.$愉快的压常数
n=5的时侯,对于每一个点$p$,建立矩阵M,其中$M[i][j] = [f[i][j][p] == 4]$
于是要找到所有的$(i, j, k)$,使得$M[i][j] = M[j][k] = M[k][i] = 1$,这些$(i,j,k)$即所有五重竹笋的外点
对于每一行,都可以用$int64(\_\_int128)$压成一个大整数,因此单次操作的时间复杂度为$O(\frac{n^2 * n} {2 * 64})$
总时间复杂度为$O(n^3 + \frac{n^4} {128})$【怎么有一种比$n=4$还快的错觉
综上。。。总算是搞完了。。理论复杂度在$n=200$的时候大概能做
而最少的$n=124$即可做一个六重蓝竹笋,算法复杂度还是很可观的
【你要问我$n$更大怎么办?$random\_shuffle()$大法好!