为防止广告,目前nocow只有登录用户能够创建新页面。如要创建页面请先登录/注册(新用户需要等待1个小时才能正常使用该功能)。

USACO/vans

来自NOCOW
跳转到: 导航, 搜索
 这篇文章可以证实是由NOCOW用户原创,不存在任何版权争议。
 本文作者同意以GNU FDLCC-by-saGNU LGPL(如果适用)三种版权发布此文章(不包括翻译文章中属于原始所有者的部分版权)。
 如果你修改了这篇文章并且不同意用GNU FDL以外的版权发布,可以换一个版权模板或者移除此模板。
这是USACO Chapter 6 .1中的OI题目Postal Vans介绍及题解,参见 翻译C语言代码C++语言代码Pascal语言代码


目录

[编辑] 问题分析

诡异算法 by Maigo(至今不知道原理是什么): 设a[i]表示第i列的左上和左下角有直线连通时的路径数,b[i]表示第i列的左上和左下角没有直线连通时的路径数,则有: b[i]:=a[i-1]+b[i-1]; a[i]=2+a[i-2]+2(a[i-2]+b[i-2]+a[i-1]+b[i-1]+...) =2+a[i-2]+2(b[i-1]+b[i-2]+...) 其中a[i]的值可以在计算过程中累加。 这样算法的时间复杂度仅为O(n)。加上高精度运算也能轻松通过。

在这再加一些 来自BillyLinux大牛{http://billylinux.blog.hexun.com/10542440_d.html} 这一题可以用DP解决:

考虑到要经过每一个点,那么对于最后形成的路,每一竖条横向的路不是4条就是2条,总共8种(不考虑路径方向):

1   2   3   4   5   6   7   8

— — —          — —

—       — —    — —

   —    —    — — —

—              — — — —

(7中最上面的与最下面的相连、8中最上面的与第二个相连)

并且对于经过最后面的4个点,路径形状只可能是两种(3、8),于是我们定义两个状态

a[i]——有i竖条,以3号形状结尾的路径数

b[i]——有i竖条,以8号形状结尾的路径数

例如:对于i=3:


a[3]=2 b[3]=2

接下来的问题,就是如何进行状态转移:

我们考虑下面的几种情况:

对于a[i],它可以接在a[i-2]、a[i-3]……与b[i-2]、b[i-3]……上(这里的接上,指的是中间不出现3号与8号路径),并且除了a[i-2]以外,其他都有两种接法(a[i-2]有3种),因此经过分类,我们可以得到:

a[i]=2*(a[i-2]+a[i-3]+……+a[2]+b[i-2]+b[i-3]+……+b[2]+1)+a[i-2]

而对于b[i],不难发现,他只能接在a[i-1]与b[i-1]上,因此有

b[i]=a[i-1]+b[i-1]

于是我们可以将a[i]化简为

a[i]=a[i-2]+2+2*(b[i-1]+b[i-2]+……b[3])

至此问题大致解决,另外需要注意的是要用高精度。



这里是我写的一份详细的题解,由于里面图很多,所以不便贴在这里~~好心的管理员帮忙吧!

http://www.oibh.org/bbs/thread-16548-1-1.html(提醒:已经404)


补充一个本题的递推式(by curimit):

n≥5时,有如下的递推关系: f(n)=2f(n-1)+2f(n-2)-2f(n-3)+f(n-4)

初值: f(1)=0,f(2)=2,f(3)=4,f(4)=12

从第5项开始向后推即可。


关于上面递推式的求解方法(by Tearhap_断章):

求环路总数量等价于求起点(1,1)终点(2,1)的哈密顿路的数量*2(定义点(2,1)在(1,1)下方)

定义f[i]为i*4矩阵中(1,1)→(2,1)哈密顿路的数量

g[i]为i*4矩阵中(1,1)→(4,2)的哈密顿路数量

则f[i]=f[i-1]+g[i-1] (画画图感受一下)

然后讨论第一列点的走入走出方式(共4种,画画图)可以算出

g[i]=g1[i]+g2[i]+g3[i]+g4[i]=g[i-2]+2*f[i-1]+g[i-1]-g[i-3]

把g用f[i]-f[i-1]代进去 解函数方程

可得到以上的f[n]=2f[n-1]+2f[n-2]-2f[n-3]+f[n-4]的结论 --CD:更极品的是算出递推式的通项式,O(高精度计算)!


回LS,通项式不好说了。。不过矩阵本菜倒是推了个。。 (f1 f2 f3 f4)*矩阵=(f2 f3 f4 f5) 然后用快速幂加速就ok,下面是矩阵。。

0 0 0 1

1 0 0 -2

0 1 0 2

0 0 1 2

By SongS


很明显,这个题目也可以用基于连通性的状态压缩动态规划来做,有兴趣的可以练习练习。 很诡异啊,我用URAL1519的AC代码搞,竟然在N=30全部爆0....

[编辑] 详细的题解

精心制作了一份:————pty http://www.docin.com/p-94253938.html

[编辑] 另外一种方法

见5.4.4题解,至少这个方法勉强能过吧

贴下运行时间

USER: ****** [y1y2t341]
TASK: vans
LANG: C

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.011 secs, 9644 KB]
   Test 2: TEST OK [0.011 secs, 9644 KB]
   Test 3: TEST OK [0.011 secs, 9644 KB]
   Test 4: TEST OK [0.000 secs, 9644 KB]
   Test 5: TEST OK [0.011 secs, 9644 KB]
   Test 6: TEST OK [0.032 secs, 9644 KB]
   Test 7: TEST OK [0.043 secs, 9644 KB]
   Test 8: TEST OK [0.076 secs, 9644 KB]
   Test 9: TEST OK [0.259 secs, 9644 KB]
   Test 10: TEST OK [0.443 secs, 9644 KB]
   Test 11: TEST OK [0.907 secs, 9644 KB]

还有,可以预处理转移方案,但是我还没加上去就AC了

路人m:没看到上面的“很明显,这个题目也可以用基于连通性的状态压缩动态规划来做,有兴趣的可以练习练习。 很诡异啊,我用URAL1519的AC代码搞,竟然在N=30全部爆0....”吗?

1

[编辑] 参考代码

C

C++

Pascal

Java

个人工具