偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

C++11的Lambda使用一例:華容道求解

開發(fā) 后端
華容道是一個(gè)有益的智力游戲,游戲規(guī)則不再贅述。用計(jì)算機(jī)求解華容道也是一道不錯(cuò)的編程練習(xí)題,為了尋求最少步數(shù),求解程序一般用廣度優(yōu)先搜索算法。華容道的一種常見開局如圖 1 所示。

華容道是一個(gè)有益的智力游戲,游戲規(guī)則不再贅述。用計(jì)算機(jī)求解華容道也是一道不錯(cuò)的編程練習(xí)題,為了尋求最少步數(shù),求解程序一般用廣度優(yōu)先搜索算法。華容道的一種常見開局如圖 1 所示。

廣度優(yōu)先搜索算法求解華容道的基本步驟:

  1. 準(zhǔn)備兩個(gè)“全局變量”,隊(duì)列 Q 和和集合 S,S 代表“已知局面”。初時(shí) Q 和 S 皆為空。
  2. 將初始局面加入隊(duì)列 Q 的末尾,并將初始局面設(shè)為已知。
  3. 當(dāng)隊(duì)列不為空時(shí),從 Q 的隊(duì)首取出當(dāng)前局面 curr。如果隊(duì)列為空則結(jié)束搜索,表明無解。
  4. 如果 curr 是最終局面(曹操位于門口,圖 2),則結(jié)束搜索,否則繼續(xù)到第 5 步。
  5. 考慮 curr 中每個(gè)可以移動的棋子,試著上下左右移動一步,得到新局面 next,如果新局面未知(next ∉ S),則把它加入隊(duì)列 Q,并設(shè)為已知。這一步可能產(chǎn)生多個(gè)新局面。
  6. 回到第2步。

其中“局面已知”并不要求每個(gè)棋子的位置相同,而是指棋子的投影的形狀相同(代碼中用 mask 表示),例如交換圖 1 中的張飛和趙云并不產(chǎn)生新局面,這一規(guī)定可以大大縮小搜索空間。

以上步驟很容易轉(zhuǎn)換為 C++ 代碼,這篇文章重點(diǎn)關(guān)注的是第 5 步的實(shí)現(xiàn)。

http://s2.51cto.com/wyfs01/M00/30/C0/wKioOVJcoKSzNcvLAABFu9uq9CE012.jpg

 

  1. // 第 1 步 
  2. std::unordered_set<Mask> seen; 
  3. std::deque<State> queue; 
  4.   
  5. // 第 2 步 
  6. State initial; 
  7. // 填入 initial,略。 
  8. queue.push_back(initial); 
  9. seen.insert(initial.toMask()); 
  10.   
  11. // 第 3 步 
  12. while (!queue.empty()) 
  13.   const State curr = queue.front(); 
  14.   queue.pop_front(); 
  15.   
  16.   // 第 4 步 
  17.   if (curr.isSolved()) 
  18.     break
  19.   
  20.   // 第 5 步 
  21.   for (const State& next : curr.moves()) 
  22.   { 
  23.     auto result = seen.insert(next.toMask()); 
  24.     if (result.second) 
  25.       queue.push_back(next); 
  26.   } 

在以上原始實(shí)現(xiàn)中,curr.move() 將返回一個(gè) std::vector<State> 臨時(shí)對象。一種節(jié)省開銷的辦法是準(zhǔn)備一個(gè) std::vector<State> “涂改變量”,讓 curr.move() 反復(fù)修改它,比如改成:

  1. // 第 1 步新增一個(gè) scratch 變量 
  2. std::vector<State> nextMoves; 
  3.   
  4. // 第 3 步 
  5. while (!queue.empty()) 
  6.   // ... 
  7.   // 第 5 步 
  8.   curr.fillMoves(&nextMoves); 
  9.   for (const State& next : nextMoves) 
  10.   { /* 略 */ } 

還有一種徹底不用這個(gè) std::vector<State> 的辦法,把一部分邏輯以 lambda 的形式傳給 curr.move(),代碼的結(jié)構(gòu)基本不變:

  1. // 第 3 步 
  2. while (!queue.empty()) 
  3.   // ... 
  4.   // 第 5 步 
  5.   curr.move([&seen, &queue](const State& next) { 
  6.     auto result = seen.insert(next.toMask()); 
  7.     if (result.second) 
  8.       queue.push_back(next); 
  9.   }); 

這樣一來,主程序的邏輯依然清晰,不必要的開銷也降到了最小。

在我最早的實(shí)現(xiàn)中,curr.move() 的參數(shù)是 const std::function<void(const State&)> &,但是我發(fā)現(xiàn)這里每次構(gòu)造 std::function<void(const State&)> 對象都會分配一次內(nèi)存,似乎有些不值。因此在現(xiàn)在的實(shí)現(xiàn)中 curr.move() 是個(gè)函數(shù)模板,這樣就能自動匹配lambda參數(shù)(通常是個(gè) struct 對象),省去了 std::function的內(nèi)存分配。

本文完整的代碼見 https://github.com/chenshuo/recipes/…/puzzle/huarong.cc,需用 GCC 4.7 編譯,求解圖 1 的題目的耗時(shí)約幾十毫秒。

練習(xí):修改程序,打印每一步移動棋子的情況。

原文鏈接:http://coolshell.cn/articles/10476.html

責(zé)任編輯:陳四芳 來源: 酷殼網(wǎng)
相關(guān)推薦

2021-11-02 14:55:42

鴻蒙HarmonyOS應(yīng)用

2012-11-04 14:54:24

2021-08-25 09:54:51

鴻蒙HarmonyOS應(yīng)用

2021-10-09 14:49:50

鴻蒙HarmonyOS應(yīng)用

2017-09-25 16:55:35

2025-04-30 10:10:00

在 C++C++11Lambda

2023-09-22 22:27:54

autoC++11

2021-10-22 19:41:01

鴻蒙HarmonyOS應(yīng)用

2024-05-29 13:21:21

2020-06-01 21:07:33

C11C++11內(nèi)存

2012-05-17 09:26:43

MapReduce

2012-09-24 01:01:49

NginxNginx性能Web服務(wù)器

2009-07-16 13:03:05

ibatis resu

2025-06-04 08:50:00

LambdaC++編程

2013-12-23 09:48:43

C++鎖定模式

2020-12-22 11:20:36

鴻蒙HarmonyOS游戲

2013-09-25 14:20:46

2024-02-21 23:43:11

C++11C++開發(fā)

2013-05-30 00:49:36

C++11C++條件變量

2013-07-29 11:11:33

C++C++11
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號