NOIP--搜索与动态规划-搜索的重难点和例题解读

1. 搜索的重难点

Ø  题目的分析与搜索策略的选择。深度优先搜索和宽度优先搜索适合的题目类型不同。

Ø  搜索算法的完备性。搜索算法必须包含的最优解。

Ø  搜索算法的复杂度预测与算法优化。

2.    例题分析

例题1-1:N皇后问题       

【问题描述】在国际象棋中,皇后可以攻击与她在同一条水平线、垂直线和对角线的棋子。现在有一张N×N的国际象棋棋盘,在上面放置N个皇后。问有多少种使皇后不能互相攻击的方案?(N≤13)

【分析】本题是一个经典的深度优先搜索题。由于皇后可以攻击同一水平线的棋子,要让皇后们互相攻击不到,每一行只有一个皇后。因此,搜索策略是,逐行搜索,枚举每一行皇后的位置,如果有皇后能

互相攻击到,则回溯,否则继续下一行。

本题如果不加优化,理论最坏时间复杂度为O(NN),但实际上达不到这个复杂度,但是也容易超时。下面说一些可行的优化。

依据对称性进行优化,对于第一行,只要枚举前N/2个点即可,根据左右对称特点,复制出右边的即可。可将时间消耗减少一半。

递归时记录下一行皇后的可能位置。在递归的过程中,每放置一个皇后,更新所有该皇后可以攻击到的区域;在回溯的过程中,将这些区域清空。

状态压缩。将每一行的状态记录在一个整形变量中,并且使用位运算——这样,速度会比朴素算法的快很多。

例题1-2:走迷宫

【问题描述】现有一个m行n列的迷宫 (m≤1000, n≤1000),其中白色(0)代表可以通过,黑色(1)代表不可通过(墙)。请给出任意一条从(1,1)出发到(m,n)的最短路径。如果不能到达,输出“Failed”。下图给出了一个迷宫样例。边给出输入样例,右边给出图示:

10 8

0001000000

0101011110

0111000100

0001010111

0100010001

0111011100

1101010101

0000010000

 

 

图中,蓝色箭头所示路径即为一条可行的最短路径。

【分析】本题为经典的宽度优先搜索题。对于本题,如果使用深度优先搜索,当m和n很大时,搜索深度会非常大,而且很多节点会被重复遍历。使用宽度优先搜索,记录该节点到根节点(1,1)的距离和该距离对应的上一步节点,按照与根节点的距离进行分层搜索。具体如下:

 

(1)将根节点加入队列,并将根节点状态更新为已遍历。

(2)如果队列为空,则输出Failed,程序结束,否则进入3。

(3)从队列中弹出一个节点,如果该节点为(m,n),则按照路径上节点记录的上一步节点,回溯得到路径,程序结束,否则进入4。

(4)判断它上下左右四个节点是否可行并未遍历。更新所有未遍历的可行节到根节点的距离为当前节点加一;更新所有未遍历的可行节点上一步节点为当前节点;将它们加入队列。进入2。

由于本题中所有节点只会被更新一次,因此,整个算法复杂度为O(mn)。该算法与漫水算法(FloodFill)类似。




例题1-3:字串变换(NOIP2002)

【问题描述】已知有两个字串 A$, B$ 及一组字串变换的规则(至多6个规则):

 

A1$ -> B1$

A2$ -> B2$

规则的含义为:在 A$ 中的子串 A1$ 可以变换为 B1$、A2$ 可以变换为B2$ …。

例如:A$='abcd',B$='xyz'

变换规则为:

‘abc’->‘xu’,‘ud’->‘y’,‘y’->‘yz’

则此时,A$ 可以经过一系列的变换变为B$,其变换的过程为:

‘abcd’->‘xud’->‘xy’->‘xyz’

共进行了三次变换,使得 A$ 变换为B$。

【输入】

第一行为两个字符串A$,B$。

从第二行开始若干行,每一行均为一个变换规则。A1$ B1$;A2$ B2$;...(所有字符串长度的上限为20)。

【输出】

若在 10 步(包含 10步)以内能将 A$ 变换为 B$ ,则输出最少的变换步数;否则输出"NOANSWER!"

【样例输入】

abcd wyz

abc xu

ud y

y yz

【样例输出】

3

【分析】本题可采用双向宽度优先搜索求解。本题给出了一个非常强的限定条件,即若在10步之内不能将 A$ 变换为 B$,则判断为无解。因此,利用宽度优先搜索,深度为10。题目中给出规则数为6,对于单向宽度优先搜索,状态数最多为610,有可能超时。

再看题目,由于变换是双向的,即如果 A$ 能够通过 Ai$ Bi$ 变换到 B$,那么 B$ 也可通过相应反变换变为 A$。因此,可采用双向宽度优先搜索。从 A$ 出发搜索5层,从 B$ 出发反向搜索5层,判断有无重复。这样状态数降至2*610,肯定不会超时。

例题1-4:Mayan游戏(NOIP2011)

【问题描述】

Mayan puzzle 是最近流行起来的一个游戏。游戏界面是一个7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上。游戏通关是指在规定的步数内消除所有的方块,消除方块的规则如下:

1、每步移动可以且仅可以沿横向(即向左或向右)拖动某一方块一格:当拖动这一方块时,如果拖动后到达的位置(以下称目标位置)也有方块,那么这两个方块将交换位置(参见输入输出样例说明中的图6 到图7);如果目标位置上没有方块,那么被拖动的方块将从原来的竖列中抽出,并从目标位置上掉落(直到不悬空,参见下面图1 和图2);

 

 

1、任一时刻,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则它们将立即被消除(参见图1 到图3)。

注意:

a) 如果同时有多组方块满足消除条件,几组方块会同时被消除(例如下面图4,三个颜色为1 的方块和三个颜色为2 的方块会同时被消除,最后剩下一个颜色为2 的方块)。

b) 当出现行和列都满足消除条件且行列共享某个方块时,行和列上满足消除条件的所有方块会被同时消除(例如下面图5 所示的情形,5 个方块会同时被消除)。

 

 

1、方块消除之后,消除位置之上的方块将掉落,掉落后可能会引起新的方块消除。注意:掉落的过程中将不会有方块的消除。上面图 1 到图3 给出了在棋盘上移动一块方块之后棋盘的变化。棋盘的左下角方块的坐标为(0,0),将位于(3, 3)的方块向左移动之后,游戏界面从图1 变成图2 所示的状态,此时在一竖列上有连续三块颜色为4 的方块,满足消除条件,消除连续3 块颜色为4 的方块后,上方的颜色为3 的方块掉落,形成图3 所示的局面。

【输入】

输入共6 行。

第一行为一个正整数 n,表示要求游戏通关的步数。

接下来的 5 行,描述7*5 的游戏界面。每行若干个整数,每两个整数之间用一个空格隔开,每行以一个0 结束,自下向上表示每竖列方块的颜色编号(颜色不多于10 种,从1 开始顺序编号,相同数字表示相同颜色)。输入数据保证初始棋盘中没有可以消除的方块。

【输出】

如果有解决方案,输出n 行,每行包含3 个整数x,y,g,表示一次移动,每两个整数之间用一个空格隔开,其中(x,y)表示要移动的方块的坐标,g 表示移动的方向,1 表示向右移动,-1 表示向左移动。注意:多组解时,按照x 为第一关健字,y 为第二关健字,1优先于-1,给出一组字典序最小的解。游戏界面左下角的坐标为(0,0)。如果没有解决方案,输出一行,包含一个整数-1。
       【样例输入】

3

1 0

2 1 0

2 3 4 0

3 1 0

2 4 3 4 0

【样例输出】

2 1 1

3 1 1

3 0 1

【样例说明】

按箭头方向的顺序分别为图 6 到图11

 

 

样例输入的游戏局面如上面第一个图片所示,依次移动的三步是:(2,1)处的方格向右移动,(3,1)处的方格向右移动,(3,0)处的方格向右移动,最后可以将棋盘上所有方块消除。

【数据范围】

对于 30%的数据,初始棋盘上的方块都在棋盘的最下面一行;

对于 100%的数据,0 < n≤5。

【分析】本题是一道比较复杂的搜索题。搜索时,按照字典序从小到大进行枚举,递归。本题的剪枝方案有:

(1)   搜索有层数限制,不用搜太多层

(2)   当左右两个点相同时,移动和不移动是一样的,则我们不用移动。

(3)   搜索每一个点,我们会发现将F[i,j]向右移和将F[i+1,j]向左移是一样的,则我们只搜索向右移的。

实际上,本题由于时限比较宽松,不用加太多优化就可以过,难点在于每一步枚举之后的状态更新较为繁琐,需注意。

 

NOIP信息学视频地址

视频地址

链接:https://pan.baidu.com/s/1tHo1DFMaDuMZAemNH60dmw 
提取码:7jgr

posted @ 2020-10-22 15:57  tianli3151  阅读(405)  评论(0编辑  收藏  举报