高级本分治应用2文档格式.docx
- 文档编号:19769240
- 上传时间:2023-01-10
- 格式:DOCX
- 页数:18
- 大小:65.21KB
高级本分治应用2文档格式.docx
《高级本分治应用2文档格式.docx》由会员分享,可在线阅读,更多相关《高级本分治应用2文档格式.docx(18页珍藏版)》请在冰豆网上搜索。
由于你使用的是计算机,所以实现时间为1s。
【输入】
输入文件共2行。
第一行:
k,即给定被填补迷宫的大小为2k(0<
k≤10);
第二行:
xy,即给出公主所在方格的坐标(x为行坐标,y为列坐标),x和y之间有一个空格隔开。
【输出】
将迷宫填补完整的方案:
每一补(行)为xyc(x,y为毯子拐角的行坐标和列坐标,c为使用毯子的形状,具体见上面的图1,毯子形状分别用1、2、3、4表示,x、y、c之间用一个空格隔开)。
blank.inblank.out
3551
33224
114
143
412
441
273
154
183
363
481
722
514
632
812
841
771
661
583
852
881
分治思想和递归程序设计。
拿到这个问题后,便有一种递归重复的感觉。
首先对最简单的情况(即k=1)进行分析:
公主只会在4个方格中的一个:
左上角:
则使用3号毯子补,毯子拐角坐标位于(2,2);
{下面就简称为毯子坐标}
左下角:
则使用2号毯子补,毯子拐角坐标位于(1,2);
右上角:
则使用1号毯子补,毯子拐角坐标位于(2,1);
右下角:
则使用4号毯子补,毯子拐角坐标位于(1,1);
其实这样不能说明什么问题,但是继续讨论就会有收获,即讨论k=2的情况(如图4-1):
#
●
○
我们假设公主所在的位置用实心圆表示,即上图中的(1,4),那么我们就可以把1号毯子放在(2,3)处,这样就将(1,3)至(2,4)的k=1见方全部覆盖(#表示地毯)。
接下来就是3个k=1的见方继续填满,这样问题就归结为k=1的情况了,但是有一点不同的是:
没有“公主”了,每一个k=1的小见方都会留下一个空白(即上图中的空心圆),那么空白就有:
1*3=3个,组合后便又是一个地毯形状。
好了,现在有感觉了吧,我们用分治法来解决它!
对于任意k>
1的宫殿,均可以将其化分为4个k/2大小的宫殿,先看一下公主站的位置是属于哪一块,因为根据公主所在的位置,我们可以确定中间位置所放的毯子类型,再递归处理公主所站的那一块,直到出现边界条件k=1的情况,然后在公主边上铺上一块合适的地毯,递归结束。
由于要递归到每一格,复杂度就是面积,就是O(22*k*k)。
4.3平面上的最接近点对
源程序名nearest.?
可执行文件名nearest.exe
输入文件名nearest.in
输出文件名nearest.out
给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的。
n;
2≤n≤60000
接下来n行:
每行两个实数:
xy,表示一个点的行坐标和列坐标,中间用一个空格隔开。
仅一行,一个实数,表示最短距离,精确到小数点后面4位。
nearest.innearest.out
31.0000
11
12
22
【参考程序】
中位数、解析几何、时间复杂度、二分法
如果n很小,那么本题很容易。
我们只要将每一点对于其它n-1个点的距离算出,找出最小距离即可。
时间复杂度O(n2)。
但本题n很大,显然会超时。
所以我们要寻找更快的解决问题的方法。
我们首先想到能不能缩小计算的规模,即把n个点的问题分治成一些小规模的问题呢?
由于二维情况下的问题计算过于复杂,所以先讨论一维的情况,假设点集为S。
我们用X轴上某个点m将点集S划分为2个子集S1和S2,使得S1={x∈S|x≤m};
S2={x∈S|x>
m}。
这样一来,对于所有p∈S1和q∈S2有p<
q。
递归地在S1和S2上找出其最接近的点对{p1,p2}和{q1,q2},并设δ=MIN{|p2-p1|,|q2-q1|},S中的最接近点对或者是{p1,p2},或者是{q1,q2},或者是某个{p3,q3},其中p3∈S1且q3∈S2。
如图4-2所示:
图4-2一维情形的分治法
我们注意到,如果S的最接近点对是{p3,q3},即|p3-q3|<
δ,则p3和q3两者与m的距离不超过δ,即|p3-m|<
δ,|q3-m|<
δ,也就是说,p3∈(m-δ,m),q3∈(m,m+δ)。
由于每个长度为δ的半闭区间至多包含S1中的一个点,并且m是S1和S2的分割点,因此(m-δ,m)中至多包含S中的一个点,则此点就是S1中的最大点。
同理,如果(m-δ,m)中有S中的点,则此点就是S2中最小点。
因此,我们用线性时间就可以将S1的解和S2的解合并成为S的解。
也就是说,按这种分治策略,合并可在O(n)时间内完成。
这样是否就可以得到一个有效算法了呢?
还有一个问题有待解决,即分割点m的选择,即S1和S2的划分。
选取分割点m的一个基本要求是由此导出集合S的一个线性分割,即S=S1∪S2,S1≠φ,S2≠φ,且S1∈{x|x≤m},S2∈{x|x>
容易看出,如果选取m=(MAX(S)+MIN(S))/2,可以满足线性分割的要求。
选取分割点后,再用O(n)时间即可将S划分成S1={x∈S|x≤m}和S2={x∈S|x>
然而,这样选取分割点m,有可能造成划分出的子集S1和S2的不平衡。
例如在最坏情况下,S1只有1个,S2有n-1个,由此产生的分治在最坏情况下所需的时间T(n)应满足递归方程:
T(n)=T(n-1)+O(n)
它的解是T(n)=O(n2)。
这种效率降低的现象可以通过分治中“平衡子问题”的方法加以解决。
也就是说,我们可以通过适当选择分割点m,使S1和S2中有大致相等个数的点。
自然地,我们会想到用S的n个点的坐标的中位数来作分割点。
这样一来,我们就能在O(n)的时间里确定m(证明略),从而得到效率相对较高的分割点。
至此,我们可以设计出一个求一维点集S中最接近点对的距离的算法:
Functionnpair1(S);
Begin
IfS中只有2个点
Thenδ:
=|x[2]-x[1]|
ElseifS中只有1个点Thenδ:
=∞
Elsebegin
M:
=S中各点的坐标值的中位数;
构造S1和S2;
{S1∈{x|x≤m},S2∈{x|x>
m}}
δ1:
=npair1(S1);
δ2:
=npair1(S2);
P:
=max(S1);
Q:
=min(S2);
δ:
=min(δ1,δ2,q-p);
end;
Exit(δ)
End;
由以上的分析可知,该算法的分割步骤总共耗时O(n)。
因此,算法耗费的计算时间T(n)满足递归方程:
T
(2)=1
T(n)=2T(n/2)+O(n);
解此递归方程可得T(n)=O(n*Log2n)。
这个一维问题的算法看上去比用排序加扫描更加复杂,然而它可以推广到二维。
假设S为平面上的点集,每个点都有2个坐标值x和y。
为了将点集S线性分割为大小大致相等的2个子集S1和S2,我们选取一垂直线l:
x=m来作为分割直线。
其中m为S中各点X坐标的中位数。
由此将S分割为S1={p∈S|x(p)≤m}和S2={p∈S|x(p)>
从而使S1和S2分别位于直线l的左侧和右侧,且S=S1∪S2。
由于m是S中各点X坐标值的中位数,因此S1和S2中的点数大致相等。
递归地在S1和S2上求解最接近点对问题,我们分别得到S1和S2中的最小距离δ1和δ2。
现设δ=min(δ1,δ2)。
若S的最接近点对(p,q)之间的距离d(p,q)<
δ,则p和q必分属于S1和S2。
不妨设p∈S1,q∈S2。
那么,p和q距直线L的距离均小于δ。
因此,我们若用P1和P2分别表示直线L的左边和右边的宽为δ的2个垂直长条,则p∈P1且q∈P2,如图4-3所示:
据直线L的距离小于δ的所有点
在一维的情形下,距分割点距离为δ的2个区间(m-δ,m),(m,m+δ)中最多各有S中一个点,因而这2点成为惟一的未检查过的最接近点对候选者。
二维的情形则要复杂一些,此时,P1中所有点与P2中所有点构成的点对均为最接近点对的候选者。
在最坏情况下有
对这样的候选者。
但是P1和P2中的点具有以下的稀疏性质,它使我们不必检查所有这
对候选者。
考虑P1中任意一点p,它若与P2中的点q构成最接近点对的候选者,则必有d(p,q)<
δ。
满足这个条件的P2中的点有多少个呢?
容易看出这样的点一定落在一个δ*2δ的矩形R中(如图4-4所示)。
由δ的意义可知,P2中任何2个S中的点的距离都不小于δ。
由此而来可以推出矩形R中最多只有6个δ/2*2/3*δ的矩形(如图4-5所示)。
图4-4包含点q的δ*2δ矩形R图4-5图4-6
若矩形R中有多于6个S中的点,则由鸽笼原理易知至少有一个δ/2*2/3*δ的小矩形中有2个以上S中的点。
设U,V是这样2个点,它们位于同一小矩形中,则:
≤
因此,
。
这与δ的意义相矛盾。
也就是说矩形R中最多只有6个S中的点。
图4-6是矩形R中含有S中的6个点的极端情形。
由于这种稀疏性质,对于P1中任一点p,P2中最多只有6个点与它构成最接近点对的候选者。
因此,在分治的合并步骤中,我们最多需要检查
对候选者,而不是
这是否就意味着我们可以在O(n)时间内完成分治法的合并步骤呢?
现在还不能确定,因为我们还不知道要检查哪6个点。
为了解决这个问题,我们可以将p和P2中所有S2的点投影到垂线L上。
由于能与p点一起构成最接近点对候选者的S2中点一定在矩形R中,所以它们在直线L上的投影距p在L上投影点的距离小于δ。
由上面的分析可知,这种投影点最多只有6个。
因此,若将P1和P2中所有S的点按其Y坐标排好序,则对P1中所有点,对排好序的点列作一次扫描,就可以找出所有最接近点对的候选者,对P1中每一点最多只要检查P2中排好序的相继6个点。
至此,我们得出用分治法求二维最接近点对距离的算法:
Functionnpair(s);
=S中这2点的距离
ElseifS中只有1个点
(1)m:
=S中各点X坐标值的中位数;
(2)δ1:
(3)δm:
=min(δ1,δ2);
(4)设P1是S1中距垂直分割线L的距离在δm之间的所有点组成的集合,
P2是S2中距分割线L的距离在δm之间的所有点组成的集合。
将P1
和P2中的点依其Y坐标值从小到大排序,并设P1*和P2*是相应的已
排好序的点列;
(5)通过扫描P1*,对于P1*中每个点检查P2*中与其距离在δm之内的所
有点(最多6个)可以完成合并。
当P1*中的扫描指针可在宽为2*δm
的一个区间内移动。
设δ1是按这种扫描方式找到的点对间的最小距
离;
(6)δ:
=min(δm,δt);
下面我们来分析上述算法的时间复杂性。
设对于n个点的平面点集S,在
(1)和(5)步用了O(n)时间,(3)和(6)用的是常数时间,
(2)则用了
时间,而在(4),最坏情况要O(nlog2n)时间,仍然无法承受,所以我们在整个程序的开始时,就先将S中的点对按Y座标值排序,这样一来(4)和(5)两步的时间就只需O(n)的时间了,所以总的计算时间同样满足:
T
(2)=1,
由此,该问题的时间复杂度为O(nlog2n),在渐进的意义下为最优算法了。
空间复杂度为O(n)。
4.4求方程的根
源程序名equation.?
可执行文件名equation.exe
输入文件名equation.in
输出文件名equation.out
输入m,n,p,a,b,求方程f(x)=mx+nx-px=0在[a,b]内的根。
m,n,p,a,b均为整数,且a<
b;
m,n,p都大于等于1。
如果有根,则输出,精确到1E-11;
如果无方程根,则输出“NO”。
equation.inequation.out
234121.5071265916E+00
2.9103830457E-11
首先这是一个单调递增函数,对于一个单调递增(或递减)函数,如图4-7所示,判断在[a,b]范围内是否有解,解是多少。
方法有多种,常用的一种方法叫“迭代法”,也就是“二分法”。
先判断f(a)·
f(b)≤0,如果满足则说明在[a,b]范围内有解,否则无解。
如果有解再判断x=(a+b)/2是不是解,如果是则输出解结束程序,否则我们采用二分法,将范围缩小到[a,x)或(x,b],究竟在哪一半区间里有解,则要看是f(a)·
f(x)<
0还是f(x)·
f(b)<
0。
当然对于yx,我们需要用换底公式把它换成exp(xln(y))。
4.5小车问题
源程序名car.?
可执行文件名car.exe
输入文件名car.in
输出文件名car.out
甲、乙两人同时从A地出发要尽快同时赶到B地。
出发时A地有一辆小车,可是这辆小车除了驾驶员外只能带一人。
已知甲、乙两人的步行速度一样,且小于车的速度。
问:
怎样利用小车才能使两人尽快同时到达。
仅一行,三个数据分别表示AB两地的距离s,人的步行速度a,车的速度b。
两人同时到达B地需要的最短时间。
car.incar.out
1205259.6000000000E+00
最佳方案为:
甲先乘车到达K处后下车步行,小车再回头接已走到C处的乙,在D处相遇后,乙再乘车赶往B,最后甲、乙一起到达B地。
这样问题就转换成了求K处的位置,我们用二分法,不断尝试,直到满足同时到达的时间精度。
算法框架如下:
(1)输入s,a,b;
(2)c0:
=0;
c1:
=s;
c:
=(c0+c1)/2;
(3)求t1,t2;
(4)如果t1<
t2,那么c:
=(c0+c)/2
否则c:
=(c+c1)/2;
反复执行(3)和(4),直到abs(t1-t2)满足精度要求(即小于误差标准)。
4.6黑白棋子的移动
源程序名chessman.?
可执行文件名chessman.exe
输入文件名chessman.in
输出文件名chessman.out
有2n个棋子(n≥4)排成一行,开始为位置白子全部在左边,黑子全部在右边,如下图为n=5的情况:
○○○○○●●●●●
移动棋子的规则是:
每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。
每次移动必须跳过若干个棋子(不能平移),要求最后能移成黑白相间的一行棋子。
如n=5时,成为:
○●○●○●○●○●
任务:
编程打印出移动过程。
chessman.inchessman.out
7step0:
ooooooo*******--
step1:
oooooo--******o*
step2:
step3:
ooooo--*****o*o*
step4:
ooooo*****--o*o*
step5:
oooo--****o*o*o*
step6:
oooo****--o*o*o*
step7:
ooo--***o*o*o*o*
step8:
ooo*o**--*o*o*o*
step9:
o--*o**oo*o*o*o*
step10:
o*o*o*--o*o*o*o*
step11:
--o*o*o*o*o*o*o*
【问题分析】
我们先从n=4开始试试看,初始时:
○○○○●●●●
第1步:
○○○——●●●○●(—表示空位)
第2步:
○○○●○●●——●
第3步:
○——●○●●○○●
第4步:
○●○●○●——○●
第5步:
——○●○●○●○●
如果n=5呢?
我们继续尝试,希望看出一些规律,初始时:
○○○○○●●●●●
○○○○——●●●●○●
○○○○●●●●——○●
这样,n=5的问题又分解成了n=4的情况,下面只要再做一下n=4的5个步骤就行了。
同理,n=6的情况又可以分解成n=5的情况,……,所以,对于一个规模为n的问题,我们很容易地就把它分治成了规模为n-1的相同类型子问题。
数据结构如下:
数组c[1..max]用来作为棋子移动的场所,初始时,c[1]~c[n]存放白子(用字符o表示),c[n+1]~c[2n]存放黑子(用字符*表示),c[2n+1],c[2n+2]为空位置(用字符—表示)。
最后结果在c[3]~c[2n+2]中。
4.7麦森数(NOIP2003)
源程序名mason.?
可执行文件名mason.exe
输入文件名mason.in
输出文件名mason.out
形如2p-1的素数称为麦森数,这时P一定也是个素数。
但反过来不一定,即如果P是个素数,2p-1不一定也是素数。
到1998年底,人们已找到了37个麦森数。
最大的一个是P=3021377,它有909526位。
麦森数有许多重要应用,它与完全数密切相关。
从文件中输入P(1000<
P<
3100000),计算2p-1的位数和最后500位数字(用十进制高精度数表示)。
文件中只包含一个整数P(1000<
3100000)。
十进制高精度数2p-1的位数;
第2~11行:
十进制高精度数2p-1的最后500位数字(每行输出50位,共输出10行,不足500位时高位补0);
不必验证2p-1与P是否为素数。
mason.in
1279
mason.out
386
00000000000000000000000000000000000000000000000000
00000000000000104079321946643990819252403273640855
38615262247266704805319112350403608059673360298012
23944173232418484242161395428100779138356624832346
49081399066056773207629241295093892203457731833496
61583550472959420547689811211693677147548478866962
50138443826029173234888531116082853841658502825560
46662248318909188018470682222031405210266984354887
32958028878050869736186900714720710555703168729087
本题的解题方法很多,其中分治也是一种巧妙的方法。
首先可以想到:
2n=(2ndiv2)2*2nmod2,即:
如果要计算2n,就要先算出2ndiv2,然后用高精度乘法算它的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 高级 分治 应用