经验大分享:Sicily1153

简介: 经验大分享:Sicily1153

代码地址:

题目如下:

1153. 马的周游问题

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge

Description

和题目C同样的任务,这里只是把棋盘扩大到标准的国际象棋。对这样一个8 8的棋盘用同样的方法编号如下:

1 2 3 4 5 6 7 8

9 10 11 12 13 14 15 16

17 18 19 20 21 22 23 24

25 26 27 28 29 30 31 32

33 34 35 36 37 38 39 40

41 42 43 44 45 46 47 48

49 50 51 52 53 54 55 56

57 58 59 60 61 62 63 64

Input

输入有若干行。每行一个整数N(1<=N<=64),表示马的起点。最后一行用-1表示结束,不用处理。

Output

对输入的每一个起点,求一条周游线路。对应地输出一行,有64个整数,从起点开始按顺序给出马每次经过的棋盘方格的编号。相邻的数字用一个空格分开。

典型的搜索问题,1152数据规模较小,直接DFS就可以过,然而1153不行,以下为超时代码(>0.99s):

1 // Problem#: 1153

2 // Submission#: 3914599

3 // The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License

4 // URI:

5 // All Copyright reserved by Informatic Lab of Sun Yat-sen University

6 #include

7 #include

8

9 bool visited【8】【8】;

10 int y_direction【8】 = {-2, -2, -1, -1, 1, 1, 2, 2};

11 int x_direction【8】 = {-1, 1, 2, -2, 2, -2, -1, 1};

12 int record【64】;

13 bool found;

14

15 inline bool is_valid(int x, int y) {

16 return x >= 0 x < 8 y >= 0 y < 8;

17 }

18

19 inline int get_number(int x, int y) {

20 return x 8 + y + 1;

21 }

22

23 void dfs(int x, int y, int step) {

24 if (visited【x】【y】 || found)

25 return;

26 visited【x】【y】 = true;

27 record【step】 = get_number(x, y);

28 if (step == 63) {

29 found = true;

30 return;

31 }

32 int temp_x, temp_y;

33 for (int i = 0; i < 8; i++) {

34 temp_x = x + x_direction【i】, temp_y = y + y_direction【i】;

35 if (is_valid(temp_x, temp_y) !visited【temp_x】【temp_y】)

36 dfs(temp_x, temp_y, step + 1);

37 }//代码效果参考:http://www.ezhiqi.com/zx/art_822.html

38 visited【x】【y】 = false;

39 }

40

41 int main() {

42 int n;

43 while (scanf("%d", n) n != -1) {

44 found = false;

45 memset(visited, 0, sizeof(visited));

46 dfs((n - 1) / 8, (n - 1) % 8, 0);

47 for (int i = 0; i < 63; i++)

48 printf("%d ", record【i】);

49 printf("%d\n", record【63】);

50 }

51 return 0;

52 }

怎么优化?

答案是: 启发式搜索。

启发式搜索其实很简单,就是在DFS的时候正常情况下是按照固定的顺序对树的节点进行访问的(例如从左到右)。

而启发式搜索则是在DFS搜索的时候对树节点的访问加入一个贪心策略,让每次往下搜索的顺序是有策略性的,有启发性的。(这个贪心策略是为了指向最终的终点)。

那么在马周游问题里面怎么在DFS里面加入这个贪心策略使这个搜索更聪明呢?(更快找到终点)

之前Wansdorff在1823年给出了这个启发策略。

Warnsdorff's rule

Warnsdorf's rule is a heuristic for finding a knight's tour. We move the knight so that we always proceed to the square from which the knight will have the fewest onward moves. When calculating the number of onward moves for each candidate square, we do not count moves that revisit any square already visited. It is, of course, possible to have two or more choices for which the number of onward moves is equal; there are various methods for breaking such ties, including one devised by Pohl 【14】 and another by Squirrel and Cull.【15】

好,尝试一下,在延伸树的支点的时候对每个支点加权排序之后再遍历。

代码如下:

1 #include

2 #include

3 #include

4 #include

5

6 bool visited【8】【8】;

7 int y_direction【8】 = {-2, -2, -1, -1, 1, 1, 2, 2};

8 int x_direction【8】 = {-1, 1, 2, -2, 2, -2, -1, 1};

9 int record【64】;

10 bool found;

11

12 struct Node {

13 int x, y, weight;

14 Node(int x, int y, int weight) {

15 this->x = x;

16 this->y = y;

17 this->weight = weight;

18 }

19 bool operator<(const Node node) const {

20 return weight [span style="color: rgba(0, 0, 0, 1)"> node.weight;

21 }

22 };

23

24 inline bool is_valid(int x, int y) {

25 return x >= 0 x < 8 y >= 0 y < 8;

26 }

27

28 inline int get_number(int x, int y) {

29 return x * 8 + y + 1;

30 }

31

32 inline int get_weight(int x, int y) {

33 int temp_x, temp_y, weight = 0;

34 for (int i = 0; i < 8; i++) {

35 temp_x = x + x_direction【i】, temp_y = y + y_direction【i】;

36 if (is_valid(temp_x, temp_y) !visited【temp_x】【temp_y】)

37 weight++;

38 }

39 return weight;

40 }

41

42 void dfs(int x, int y, int step) {

43 if (visited【x】【y】 || found)

44 return;

45 visited【x】【y】 = true;

46 record【step】 = get_number(x, y);

47 if (step == 63) {

48 found = true;

49 return;

50 }

51 int temp_x, temp_y;

52 std::vector v;

53 for (int i = 0; i < 8; i++) {

54 temp_x = x + x_direction【i】, temp_y = y + y_direction【i】;

55 if (is_valid(temp_x, temp_y) !visited【temp_x】【temp_y】)

56 v.push_back(Node(temp_x, temp_y, get_weight(temp_x, temp_y)));

57 }

58 std::sort(v.begin(), v.end());

59 for (int i = 0; (size_t)i < v.size(); i++)

60 dfs(v【i】.x, v【i】.y, step + 1);

61 visited【x】【y】 = false;

62 }

63

64 int main() {

65 int n;

66 while (scanf("%d", n) n != -1) {

67 found = false;

68 memset(visited, 0, sizeof(visited));

69 dfs((n - 1) / 8, (n - 1) % 8, 0);

70 for (int i = 0; i < 63; i++)

71 printf("%d ", record【i】);

72 printf("%d\n", record【63】);

73 }

74 return 0;

75 }

运用此策略惊人的达到了0.00s,在性能的提升上我确实没想到能提升这么多。

以下为两个版本代码提交截图:

相关文章
|
存储 前端开发 定位技术
GIS前端编程 地图常用操作
GIS前端编程 地图常用操作
397 0
|
资源调度
一天掌握latex论文编辑,从标题作者,段落,数学公式,图片,图表,到参考文献全流程
一天掌握latex论文编辑,从标题作者,段落,数学公式,图片,图表,到参考文献全流程
1360 0
|
Kubernetes 关系型数据库 分布式数据库
PolarDB在混合云环境下的部署策略与挑战
【9月更文挑战第5天】随着云计算技术的发展,混合云成为众多企业首选,以满足数据管理和业务扩展需求。阿里巴巴自研的PolarDB是一款高性能云原生数据库,在混合云中可通过多种方式部署,如Kubernetes,实现资源弹性伸缩及自动化管理,并支持跨平台数据同步与金融级高可用性。然而,混合云环境下也带来了复杂性、成本优化及运维难度等挑战,企业需综合考虑平台兼容性、安全性和资源投入比例等问题。
297 5
|
传感器 数据采集 监控
LabVIEW电池管理系统测试平台
LabVIEW电池管理系统测试平台
232 4
|
11月前
|
JSON 安全 API
微店item_search_shop-获得店铺的所有商品API接口设计指南
本文介绍如何设计高效、安全且易用的item_search_shop API接口,用于微店商品检索和管理。关键需求包括数据完整性、高并发支持、安全性及易用性。开发者需在微店开放平台注册获取API凭证,并通过Access Token调用接口。接口支持一次性获取店铺所有商品信息,提供Python示例代码。注意事项涵盖凭证安全、异常处理和数据准确性。此API助力商家提升电商运营效率。
|
小程序 JavaScript
微信小程序实现一个简单的表格
微信小程序实现一个简单的表格
359 0
|
算法 安全 Java
(七)JVM成神路之GC分代篇:分代GC器、CMS收集器及YoungGC、FullGC日志剖析
在《GC基础篇》中曾谈到过分代以及分区回收的概念,但基础篇更多的是建立在GC的一些算法理论上进行高谈阔论,而本篇则重点会对于分代收集器的实现进行全面详解,其中会涵盖串行收集器、并行收集器、三色标记、SATB算法、GC执行过程、并发标记、CMS收集器等知识,本篇则偏重于分析GC机制的落地实现,也就是垃圾收集器(Garbage Collector)。
706 8
|
域名解析 安全 物联网
阿里云EMAS HTTPDNS 扩展全球服务节点:提升解析安全性与网络覆盖
阿里云EMAS HTTPDNS新增国内西南、华南及国际欧洲、美东服务节点,提升了全球覆盖能力与性能。作为高效域名解析服务,EMAS HTTPDNS针对互联网、汽车、物流、IOT等行业提供支持,解决了传统解析易遭劫持等问题。新增节点优化了就近调度功能,显著缩短响应时间并增强了服务稳定性和连续性,尤其为中国企业的海外业务提供了强有力的支持。此次扩展展现了阿里云对服务质量的持续追求和全球市场布局的战略思考。
|
机器学习/深度学习 TensorFlow 数据处理
分布式训练在TensorFlow中的全面应用指南:掌握多机多卡配置与实践技巧,让大规模数据集训练变得轻而易举,大幅提升模型训练效率与性能
【8月更文挑战第31天】本文详细介绍了如何在Tensorflow中实现多机多卡的分布式训练,涵盖环境配置、模型定义、数据处理及训练执行等关键环节。通过具体示例代码,展示了使用`MultiWorkerMirroredStrategy`进行分布式训练的过程,帮助读者更好地应对大规模数据集与复杂模型带来的挑战,提升训练效率。
565 0
|
机器学习/深度学习 数据可视化 算法
时间序列分解 | Matlab SGMD辛几何模态分解数据分解可视化,信号数据分解
时间序列分解 | Matlab SGMD辛几何模态分解数据分解可视化,信号数据分解