1 / 30

搜索例题讲解(威力加强版)

搜索例题讲解(威力加强版). 陈才斌 修改自梁锋课件. 6.4 王伯买鱼. 规定 最多30种鱼 对于每种鱼,最多只能买一条 有些鱼不能一起买 每条鱼有一定价钱,王伯的资金有限 目标 买尽可能多的鱼. 12. 9. 3. 5. 7. 11. 8. 王伯买鱼. 构造图 把每种鱼看成一个顶点 顶点所代表的鱼的价格作为它的权值 两种鱼之间不能共处则在它们之间连一条边. 王伯买鱼. 用集合表示王伯买了哪些鱼 表:List = {1, 2, 4, …} 向量:Vector = {1, 1, 0, 1, …}

allan
Download Presentation

搜索例题讲解(威力加强版)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 搜索例题讲解(威力加强版) 陈才斌修改自梁锋课件

  2. 6.4 王伯买鱼 • 规定 • 最多30种鱼 • 对于每种鱼,最多只能买一条 • 有些鱼不能一起买 • 每条鱼有一定价钱,王伯的资金有限 • 目标 • 买尽可能多的鱼

  3. 12 9 3 5 7 11 8 王伯买鱼 • 构造图 • 把每种鱼看成一个顶点 • 顶点所代表的鱼的价格作为它的权值 • 两种鱼之间不能共处则在它们之间连一条边

  4. 王伯买鱼 • 用集合表示王伯买了哪些鱼 • 表:List = {1, 2, 4, …} • 向量:Vector = {1, 1, 0, 1, …} • 计算机的数组:int got[30]; got[i] = 1 表示买了第i条鱼 got[i] = 0 否则

  5. 3 1 5 4 2 3 王伯买鱼 {0, 0, 0} - 0 {0, 0, 0} - 0 {1, 0, 0} - 3 {0, 0, 0} - 0 {0, 1, 0} - 4 {1, 0, 0} - 3 {1, 1, 0} - 7 {0, 0, 0} - 0 {0, 1, 0} - 4 {1, 0, 0} - 3 {1, 1, 0} - 7 {0, 0, 1} - 5 {0, 1, 1} - 9 {1, 0, 1} - 8 {1, 1, 1} - 12

  6. 王伯买鱼 • void buy ( i ) • if (i>n) 找到一个子集; • else • got[i] = 0; • buy( i+1 ); • if ( i能与已买的鱼共处 && 还有钱支付 ) • got[i] = 1; 并支付鱼的价钱; • buy( i+1 ); • got[i] = 0; 并取回鱼的价钱;

  7. 王伯买鱼 • 有n种鱼:2n个子集 • 230 = 1,073,741,824 • 把不必要的子集删除 • 可行性:发生冲突、不够钱 • 最优化:估算剩下的鱼,最多可以取多少

  8. 王伯买鱼 • 不考虑价格,最多能买多少的鱼? • 删除多少个顶点后剩下的图没有边 • 尽可能删度数大的顶点 • 2*边数 = Σ顶点度 • 认为删一个点就可以删与之度数相同的边数 {3, 2, 2, 2, 1, 1, 1}

  9. 6.5 数学家旅游 • 旅行线路要求 • 每次走的方向和前一次不同 • 每次走的距离比前一次长一步; • 不重复走同一个地方 • 要走回出发点 • 某些地方不能走(工地) • 最大边<=20 • 找出所有行走路线

  10. 数学家旅游 • 将城市看作一个坐标网格 • 起始位置为坐标原点 • 所走的每一段可以看作一条线段 • 不走同一个地方  任两条线段不重复 • 回到出发点  最后一点返回原点 • 不经过施工地点  点不可在线段上

  11. 数学家旅游 • 用数组表示网格 • 2 + 4 + 8 + … + 20 = 110 • int city[220][220]; • 假设O(110,110) • 行走路线 • 线段 —— 端点的坐标(x,y) —— 所有经过的格点 • 工地和经过的格点都是一样的,不可再走 • city[x][y] = 0 可以经过 • city[x][y] > 0 不可以经过

  12. 数学家旅游 • void search( now(x,y) ) • if (StepLength == n && 返回起点) • tot++; • StepLength++; • for ( 向左右两个方向 ) • if ( 可以往该方向走StepLength步 ) • 行走到dest(x’,y’)并标记走过的路线; • Search( dest(x’,y’) ); • 擦除这一步走过的线路,返回now(x,y); • StepLength--;

  13. StepLength = m 数学家旅游 • 当第m步向上走达(x,y) • 水平方向 • m+1, m+3, … (<=n) • 垂直方向 • m+2, m+4, … (<=n) • 不考虑工地和路线重叠 • m=2: ±3±5±7 == x

  14. 数学家旅游 • 令can[m][k]=1或0表示在数轴上连续走m,m+2,m+4…, (<=n)能否到达k • can[m][k] = can[m][-k] • can[n][n] = can[n-1][n-1] = 1 • can[m][k] = can[m+2][±k±m] • 判断 • can[m+1][x]==1 && can[m+2][y]==1 • 其它方向的行走与此类似

  15. 6.9 骑士问题 • 假设 • 8*8的国际象棋棋盘 • 不能越过有障碍物的格子“b” • 马从‘n’跳到‘N’ • 要求 • 最小的步数

  16. 骑士问题 • 问题的表示 • 马的位置:struct Pos { int x,y; } • 整个棋盘:int board[x][y];它的值可以表示到达当前格子的最少步数 • 求最短路 —— 广度搜索 • 对比:6.1马的走法

  17. 骑士问题 • void WFS () • 初始化多列 • head = 0; • tail = 1; • queue[head] = 起始位置; • visited[起始位置] = 1; • step = 0; • while ( head < tail ) • step++; • for ( queue中head到tail区间的结点 ) • 扩展节点 —— 向八个方向跳一步 • 如果马没有跳出棋盘,并且到达一个新的位置,则入队列 • 如果到达目标则停止 • 返回路径不存在

  18. 6.11 过河 • 河中有n支木桩 • 在0时刻都是降的状态 • 升起A分钟,降下B分钟,升起A分钟…… • 农夫开始在左岸(0时刻) • 每一时刻可以到左右跳最多5个桩的距离 • 要求:用最少时间到达右岸 左岸 右岸

  19. 过河 t=0 L 1 2 3 4 5 6 7 8 10 R …… ? t=1 L 1 2 3 4 5 6 7 8 10 R …… ? t=2 L 1 2 3 4 5 6 7 8 10 R …… ? t=2 L 1 2 3 4 5 6 7 8 10 R …… ? t=4 L 1 2 3 4 5 6 7 8 10 R …… …… …… ……

  20. 过河 • 问题:时间无限导致图是无限的 • 无限图搜索 • 空间无法承受 • 导致程序无法结束

  21. 过河 • 设第i支桩有A[i]时间升,B[i]时间降 • 周期:T[i] = A[i]+B[i] • 在时刻t:w = t % T[i] • 如果1<=w<=A[i],桩是升起的否则桩降下去,特别的当w=0时 • 令tf = LCM( T[1], …, T[n] ) • tf % T[i] = 0,即所有桩都降下 • T[i]<=10,所以 tf <= LCM(1, …, 10) = 2520

  22. 过河 • time = 0; • do • time++; • if (到达右岸) 成功并退出搜索; • for (0<=i<=n+1) • for (i-5<=j<=i+5) • if (在当前时间桩i是可站立的 && 上一时刻能够到达桩j) • 当前时刻可到达桩i; • while ( time <= 2520 ); • 返回:无法到达右岸

  23. 6.8 分球 • 任意两个相邻的非空的盒子里的球可以移动到两个相邻的空盒中 • 移动不能改变这两个球的排列顺序 • 目标: • 用最少的次数把所有的a都移到b的左边

  24. 分球 • 状态的总数 • 先不考虑空盒,则剩下2N-2个球排成一排 • 再放入空盒,共有2N-1个位置可以放 • N=7时,总共有12012种状态

  25. 分球 • 状态的保存 • 空盒的位置 + a球的位置 + b球的位置 • 数据结构 • struct State { int blank; //空盒位置 int a[6]; //拿走空盒后,所有a球的位置 int father; //指向父结点的位置}

  26. 分球 • 重复结点的判断 • 映射 F : State  Int (Int是非负整数集) • T : State.a  Int • F ’ : State  (blank, Int) • State F F ’ • OOab 0 (0, 0) • OOba 1 (0, 1) • aOOb 2 (1, 0) • bOOa 3 (1, 1) • abOO 4 (2, 0) • baOO 5 (2, 1)

  27. 分球 • 计算: T : State.a  Int

  28. 分球 • a[i]表示除去空盒后第i个a球所在的位置 • baabOOaabb • a[1..4] = {2, 3, 5, 6} 2N-2-k个球,其中N-1-i个a k

  29. 总结 • 明确状态表示 • 决定搜索方式 • 编写程序 • 性能的优化

  30. 吃饭时间 求BG

More Related