成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

開發 后端
華容道是一個有益的智力游戲,游戲規則不再贅述。用計算機求解華容道也是一道不錯的編程練習題,為了尋求最少步數,求解程序一般用廣度優先搜索算法。華容道的一種常見開局如圖 1 所示。

華容道是一個有益的智力游戲,游戲規則不再贅述。用計算機求解華容道也是一道不錯的編程練習題,為了尋求最少步數,求解程序一般用廣度優先搜索算法。華容道的一種常見開局如圖 1 所示。

廣度優先搜索算法求解華容道的基本步驟:

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

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

以上步驟很容易轉換為 C++ 代碼,這篇文章重點關注的是第 5 步的實現。

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.   } 

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

  1. // 第 1 步新增一個 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.   { /* 略 */ } 

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

  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.   }); 

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

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

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

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

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

責任編輯:陳四芳 來源: 酷殼網
相關推薦

2021-11-02 14:55:42

鴻蒙HarmonyOS應用

2012-11-04 14:54:24

2021-08-25 09:54:51

鴻蒙HarmonyOS應用

2021-10-09 14:49:50

鴻蒙HarmonyOS應用

2017-09-25 16:55:35

2025-04-30 10:10:00

在 C++C++11Lambda

2021-10-22 19:41:01

鴻蒙HarmonyOS應用

2023-09-22 22:27:54

autoC++11

2024-05-29 13:21:21

2020-06-01 21:07:33

C11C++11內存

2025-06-04 08:50:00

LambdaC++編程

2012-05-17 09:26:43

MapReduce

2012-09-24 01:01:49

NginxNginx性能Web服務器

2009-07-16 13:03:05

ibatis resu

2020-12-22 11:20:36

鴻蒙HarmonyOS游戲

2013-12-23 09:48:43

C++鎖定模式

2013-09-25 14:20:46

2024-02-21 23:43:11

C++11C++開發

2013-05-30 00:49:36

C++11C++條件變量

2013-07-29 11:11:33

C++C++11
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日日夜夜免费精品 | 亚洲国产自产 | 日韩av免费在线电影 | 久久精品99国产精品 | 亚洲91视频| 欧美视频三区 | 成人小视频在线观看 | 亚洲成人精品在线 | 国产精品永久免费观看 | av福利网 | 日韩在线中文字幕 | 日中文字幕在线 | 国产激情在线 | 中文字幕 在线观看 | 国产乱码久久久久久 | 久久综合入口 | 在线观看免费av网 | 精品国产31久久久久久 | 亚洲精品一区二区网址 | 国产精品精品视频一区二区三区 | 人人种亚洲 | 成人在线精品视频 | 日韩av在线免费 | 拍戏被cao翻了h承欢 | 国产精品久久久久久久久久三级 | 亚洲 欧美 另类 综合 偷拍 | 日韩成人 | 成人高清在线 | 亚洲色欲色欲www | 亚洲免费一区二区 | 欧美国产视频一区二区 | 九色在线观看 | 国产最新精品视频 | 在线观看黄色大片 | 欧美一卡二卡在线观看 | 精品国产一区二区三区久久 | 久久综合狠狠综合久久综合88 | 99热在线免费 | 国产美女黄色 | 久久精品亚洲一区二区三区浴池 | www国产成人免费观看视频,深夜成人网 |